Repository: openai/openai-python Branch: main Commit: acd0c54d8a68 Files: 1262 Total size: 5.2 MB Directory structure: gitextract_npo499yb/ ├── .devcontainer/ │ ├── Dockerfile │ └── devcontainer.json ├── .github/ │ ├── CODEOWNERS │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.yml │ │ ├── config.yml │ │ └── feature_request.yml │ ├── pull_request_template.md │ └── workflows/ │ ├── ci.yml │ ├── create-releases.yml │ ├── detect-breaking-changes.yml │ ├── publish-pypi.yml │ └── release-doctor.yml ├── .gitignore ├── .inline-snapshot/ │ └── external/ │ └── .gitignore ├── .python-version ├── .release-please-manifest.json ├── .stats.yml ├── .vscode/ │ └── settings.json ├── Brewfile ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── api.md ├── bin/ │ ├── check-release-environment │ └── publish-pypi ├── examples/ │ ├── .keep │ ├── async_demo.py │ ├── audio.py │ ├── azure.py │ ├── azure_ad.py │ ├── demo.py │ ├── generate_file.sh │ ├── image_stream.py │ ├── module_client.py │ ├── parsing.py │ ├── parsing_stream.py │ ├── parsing_tools.py │ ├── parsing_tools_stream.py │ ├── picture.py │ ├── realtime/ │ │ ├── audio_util.py │ │ ├── azure_realtime.py │ │ ├── push_to_talk_app.py │ │ └── realtime.py │ ├── responses/ │ │ ├── __init__.py │ │ ├── background.py │ │ ├── background_async.py │ │ ├── background_streaming.py │ │ ├── background_streaming_async.py │ │ ├── streaming.py │ │ ├── streaming_tools.py │ │ ├── structured_outputs.py │ │ ├── structured_outputs_tools.py │ │ └── websocket.py │ ├── responses_input_tokens.py │ ├── speech_to_text.py │ ├── streaming.py │ ├── text_to_speech.py │ ├── uploads.py │ └── video.py ├── helpers.md ├── noxfile.py ├── pyproject.toml ├── release-please-config.json ├── scripts/ │ ├── bootstrap │ ├── detect-breaking-changes │ ├── detect-breaking-changes.py │ ├── format │ ├── lint │ ├── mock │ ├── pyrightconfig.breaking-changes.json │ ├── run-pyright │ ├── test │ └── utils/ │ ├── ruffen-docs.py │ └── upload-artifact.sh ├── src/ │ └── openai/ │ ├── __init__.py │ ├── __main__.py │ ├── _base_client.py │ ├── _client.py │ ├── _compat.py │ ├── _constants.py │ ├── _exceptions.py │ ├── _extras/ │ │ ├── __init__.py │ │ ├── _common.py │ │ ├── numpy_proxy.py │ │ ├── pandas_proxy.py │ │ └── sounddevice_proxy.py │ ├── _files.py │ ├── _legacy_response.py │ ├── _models.py │ ├── _module_client.py │ ├── _qs.py │ ├── _resource.py │ ├── _response.py │ ├── _streaming.py │ ├── _types.py │ ├── _utils/ │ │ ├── __init__.py │ │ ├── _compat.py │ │ ├── _datetime_parse.py │ │ ├── _json.py │ │ ├── _logs.py │ │ ├── _proxy.py │ │ ├── _reflection.py │ │ ├── _resources_proxy.py │ │ ├── _streams.py │ │ ├── _sync.py │ │ ├── _transform.py │ │ ├── _typing.py │ │ └── _utils.py │ ├── _version.py │ ├── cli/ │ │ ├── __init__.py │ │ ├── _api/ │ │ │ ├── __init__.py │ │ │ ├── _main.py │ │ │ ├── audio.py │ │ │ ├── chat/ │ │ │ │ ├── __init__.py │ │ │ │ └── completions.py │ │ │ ├── completions.py │ │ │ ├── files.py │ │ │ ├── fine_tuning/ │ │ │ │ ├── __init__.py │ │ │ │ └── jobs.py │ │ │ ├── image.py │ │ │ └── models.py │ │ ├── _cli.py │ │ ├── _errors.py │ │ ├── _models.py │ │ ├── _progress.py │ │ ├── _tools/ │ │ │ ├── __init__.py │ │ │ ├── _main.py │ │ │ ├── fine_tunes.py │ │ │ └── migrate.py │ │ └── _utils.py │ ├── helpers/ │ │ ├── __init__.py │ │ ├── local_audio_player.py │ │ └── microphone.py │ ├── lib/ │ │ ├── .keep │ │ ├── __init__.py │ │ ├── _old_api.py │ │ ├── _parsing/ │ │ │ ├── __init__.py │ │ │ ├── _completions.py │ │ │ └── _responses.py │ │ ├── _pydantic.py │ │ ├── _realtime.py │ │ ├── _tools.py │ │ ├── _validators.py │ │ ├── azure.py │ │ └── streaming/ │ │ ├── __init__.py │ │ ├── _assistants.py │ │ ├── _deltas.py │ │ ├── chat/ │ │ │ ├── __init__.py │ │ │ ├── _completions.py │ │ │ ├── _events.py │ │ │ └── _types.py │ │ └── responses/ │ │ ├── __init__.py │ │ ├── _events.py │ │ ├── _responses.py │ │ └── _types.py │ ├── pagination.py │ ├── py.typed │ ├── resources/ │ │ ├── __init__.py │ │ ├── audio/ │ │ │ ├── __init__.py │ │ │ ├── audio.py │ │ │ ├── speech.py │ │ │ ├── transcriptions.py │ │ │ └── translations.py │ │ ├── batches.py │ │ ├── beta/ │ │ │ ├── __init__.py │ │ │ ├── assistants.py │ │ │ ├── beta.py │ │ │ ├── chatkit/ │ │ │ │ ├── __init__.py │ │ │ │ ├── chatkit.py │ │ │ │ ├── sessions.py │ │ │ │ └── threads.py │ │ │ ├── realtime/ │ │ │ │ ├── __init__.py │ │ │ │ ├── realtime.py │ │ │ │ ├── sessions.py │ │ │ │ └── transcription_sessions.py │ │ │ └── threads/ │ │ │ ├── __init__.py │ │ │ ├── messages.py │ │ │ ├── runs/ │ │ │ │ ├── __init__.py │ │ │ │ ├── runs.py │ │ │ │ └── steps.py │ │ │ └── threads.py │ │ ├── chat/ │ │ │ ├── __init__.py │ │ │ ├── chat.py │ │ │ └── completions/ │ │ │ ├── __init__.py │ │ │ ├── completions.py │ │ │ └── messages.py │ │ ├── completions.py │ │ ├── containers/ │ │ │ ├── __init__.py │ │ │ ├── containers.py │ │ │ └── files/ │ │ │ ├── __init__.py │ │ │ ├── content.py │ │ │ └── files.py │ │ ├── conversations/ │ │ │ ├── __init__.py │ │ │ ├── api.md │ │ │ ├── conversations.py │ │ │ └── items.py │ │ ├── embeddings.py │ │ ├── evals/ │ │ │ ├── __init__.py │ │ │ ├── evals.py │ │ │ └── runs/ │ │ │ ├── __init__.py │ │ │ ├── output_items.py │ │ │ └── runs.py │ │ ├── files.py │ │ ├── fine_tuning/ │ │ │ ├── __init__.py │ │ │ ├── alpha/ │ │ │ │ ├── __init__.py │ │ │ │ ├── alpha.py │ │ │ │ └── graders.py │ │ │ ├── checkpoints/ │ │ │ │ ├── __init__.py │ │ │ │ ├── checkpoints.py │ │ │ │ └── permissions.py │ │ │ ├── fine_tuning.py │ │ │ └── jobs/ │ │ │ ├── __init__.py │ │ │ ├── checkpoints.py │ │ │ └── jobs.py │ │ ├── images.py │ │ ├── models.py │ │ ├── moderations.py │ │ ├── realtime/ │ │ │ ├── __init__.py │ │ │ ├── api.md │ │ │ ├── calls.py │ │ │ ├── client_secrets.py │ │ │ └── realtime.py │ │ ├── responses/ │ │ │ ├── __init__.py │ │ │ ├── api.md │ │ │ ├── input_items.py │ │ │ ├── input_tokens.py │ │ │ └── responses.py │ │ ├── skills/ │ │ │ ├── __init__.py │ │ │ ├── content.py │ │ │ ├── skills.py │ │ │ └── versions/ │ │ │ ├── __init__.py │ │ │ ├── content.py │ │ │ └── versions.py │ │ ├── uploads/ │ │ │ ├── __init__.py │ │ │ ├── parts.py │ │ │ └── uploads.py │ │ ├── vector_stores/ │ │ │ ├── __init__.py │ │ │ ├── file_batches.py │ │ │ ├── files.py │ │ │ └── vector_stores.py │ │ ├── videos.py │ │ └── webhooks/ │ │ ├── __init__.py │ │ ├── api.md │ │ └── webhooks.py │ ├── types/ │ │ ├── __init__.py │ │ ├── audio/ │ │ │ ├── __init__.py │ │ │ ├── speech_create_params.py │ │ │ ├── speech_model.py │ │ │ ├── transcription.py │ │ │ ├── transcription_create_params.py │ │ │ ├── transcription_create_response.py │ │ │ ├── transcription_diarized.py │ │ │ ├── transcription_diarized_segment.py │ │ │ ├── transcription_include.py │ │ │ ├── transcription_segment.py │ │ │ ├── transcription_stream_event.py │ │ │ ├── transcription_text_delta_event.py │ │ │ ├── transcription_text_done_event.py │ │ │ ├── transcription_text_segment_event.py │ │ │ ├── transcription_verbose.py │ │ │ ├── transcription_word.py │ │ │ ├── translation.py │ │ │ ├── translation_create_params.py │ │ │ ├── translation_create_response.py │ │ │ └── translation_verbose.py │ │ ├── audio_model.py │ │ ├── audio_response_format.py │ │ ├── auto_file_chunking_strategy_param.py │ │ ├── batch.py │ │ ├── batch_create_params.py │ │ ├── batch_error.py │ │ ├── batch_list_params.py │ │ ├── batch_request_counts.py │ │ ├── batch_usage.py │ │ ├── beta/ │ │ │ ├── __init__.py │ │ │ ├── assistant.py │ │ │ ├── assistant_create_params.py │ │ │ ├── assistant_deleted.py │ │ │ ├── assistant_list_params.py │ │ │ ├── assistant_response_format_option.py │ │ │ ├── assistant_response_format_option_param.py │ │ │ ├── assistant_stream_event.py │ │ │ ├── assistant_tool.py │ │ │ ├── assistant_tool_choice.py │ │ │ ├── assistant_tool_choice_function.py │ │ │ ├── assistant_tool_choice_function_param.py │ │ │ ├── assistant_tool_choice_option.py │ │ │ ├── assistant_tool_choice_option_param.py │ │ │ ├── assistant_tool_choice_param.py │ │ │ ├── assistant_tool_param.py │ │ │ ├── assistant_update_params.py │ │ │ ├── chat/ │ │ │ │ └── __init__.py │ │ │ ├── chatkit/ │ │ │ │ ├── __init__.py │ │ │ │ ├── chat_session.py │ │ │ │ ├── chat_session_automatic_thread_titling.py │ │ │ │ ├── chat_session_chatkit_configuration.py │ │ │ │ ├── chat_session_chatkit_configuration_param.py │ │ │ │ ├── chat_session_expires_after_param.py │ │ │ │ ├── chat_session_file_upload.py │ │ │ │ ├── chat_session_history.py │ │ │ │ ├── chat_session_rate_limits.py │ │ │ │ ├── chat_session_rate_limits_param.py │ │ │ │ ├── chat_session_status.py │ │ │ │ ├── chat_session_workflow_param.py │ │ │ │ ├── chatkit_attachment.py │ │ │ │ ├── chatkit_response_output_text.py │ │ │ │ ├── chatkit_thread.py │ │ │ │ ├── chatkit_thread_assistant_message_item.py │ │ │ │ ├── chatkit_thread_item_list.py │ │ │ │ ├── chatkit_thread_user_message_item.py │ │ │ │ ├── chatkit_widget_item.py │ │ │ │ ├── session_create_params.py │ │ │ │ ├── thread_delete_response.py │ │ │ │ ├── thread_list_items_params.py │ │ │ │ └── thread_list_params.py │ │ │ ├── chatkit_workflow.py │ │ │ ├── code_interpreter_tool.py │ │ │ ├── code_interpreter_tool_param.py │ │ │ ├── file_search_tool.py │ │ │ ├── file_search_tool_param.py │ │ │ ├── function_tool.py │ │ │ ├── function_tool_param.py │ │ │ ├── realtime/ │ │ │ │ ├── __init__.py │ │ │ │ ├── conversation_created_event.py │ │ │ │ ├── conversation_item.py │ │ │ │ ├── conversation_item_content.py │ │ │ │ ├── conversation_item_content_param.py │ │ │ │ ├── conversation_item_create_event.py │ │ │ │ ├── conversation_item_create_event_param.py │ │ │ │ ├── conversation_item_created_event.py │ │ │ │ ├── conversation_item_delete_event.py │ │ │ │ ├── conversation_item_delete_event_param.py │ │ │ │ ├── conversation_item_deleted_event.py │ │ │ │ ├── conversation_item_input_audio_transcription_completed_event.py │ │ │ │ ├── conversation_item_input_audio_transcription_delta_event.py │ │ │ │ ├── conversation_item_input_audio_transcription_failed_event.py │ │ │ │ ├── conversation_item_param.py │ │ │ │ ├── conversation_item_retrieve_event.py │ │ │ │ ├── conversation_item_retrieve_event_param.py │ │ │ │ ├── conversation_item_truncate_event.py │ │ │ │ ├── conversation_item_truncate_event_param.py │ │ │ │ ├── conversation_item_truncated_event.py │ │ │ │ ├── conversation_item_with_reference.py │ │ │ │ ├── conversation_item_with_reference_param.py │ │ │ │ ├── error_event.py │ │ │ │ ├── input_audio_buffer_append_event.py │ │ │ │ ├── input_audio_buffer_append_event_param.py │ │ │ │ ├── input_audio_buffer_clear_event.py │ │ │ │ ├── input_audio_buffer_clear_event_param.py │ │ │ │ ├── input_audio_buffer_cleared_event.py │ │ │ │ ├── input_audio_buffer_commit_event.py │ │ │ │ ├── input_audio_buffer_commit_event_param.py │ │ │ │ ├── input_audio_buffer_committed_event.py │ │ │ │ ├── input_audio_buffer_speech_started_event.py │ │ │ │ ├── input_audio_buffer_speech_stopped_event.py │ │ │ │ ├── rate_limits_updated_event.py │ │ │ │ ├── realtime_client_event.py │ │ │ │ ├── realtime_client_event_param.py │ │ │ │ ├── realtime_connect_params.py │ │ │ │ ├── realtime_response.py │ │ │ │ ├── realtime_response_status.py │ │ │ │ ├── realtime_response_usage.py │ │ │ │ ├── realtime_server_event.py │ │ │ │ ├── response_audio_delta_event.py │ │ │ │ ├── response_audio_done_event.py │ │ │ │ ├── response_audio_transcript_delta_event.py │ │ │ │ ├── response_audio_transcript_done_event.py │ │ │ │ ├── response_cancel_event.py │ │ │ │ ├── response_cancel_event_param.py │ │ │ │ ├── response_content_part_added_event.py │ │ │ │ ├── response_content_part_done_event.py │ │ │ │ ├── response_create_event.py │ │ │ │ ├── response_create_event_param.py │ │ │ │ ├── response_created_event.py │ │ │ │ ├── response_done_event.py │ │ │ │ ├── response_function_call_arguments_delta_event.py │ │ │ │ ├── response_function_call_arguments_done_event.py │ │ │ │ ├── response_output_item_added_event.py │ │ │ │ ├── response_output_item_done_event.py │ │ │ │ ├── response_text_delta_event.py │ │ │ │ ├── response_text_done_event.py │ │ │ │ ├── session.py │ │ │ │ ├── session_create_params.py │ │ │ │ ├── session_create_response.py │ │ │ │ ├── session_created_event.py │ │ │ │ ├── session_update_event.py │ │ │ │ ├── session_update_event_param.py │ │ │ │ ├── session_updated_event.py │ │ │ │ ├── transcription_session.py │ │ │ │ ├── transcription_session_create_params.py │ │ │ │ ├── transcription_session_update.py │ │ │ │ ├── transcription_session_update_param.py │ │ │ │ └── transcription_session_updated_event.py │ │ │ ├── thread.py │ │ │ ├── thread_create_and_run_params.py │ │ │ ├── thread_create_params.py │ │ │ ├── thread_deleted.py │ │ │ ├── thread_update_params.py │ │ │ └── threads/ │ │ │ ├── __init__.py │ │ │ ├── annotation.py │ │ │ ├── annotation_delta.py │ │ │ ├── file_citation_annotation.py │ │ │ ├── file_citation_delta_annotation.py │ │ │ ├── file_path_annotation.py │ │ │ ├── file_path_delta_annotation.py │ │ │ ├── image_file.py │ │ │ ├── image_file_content_block.py │ │ │ ├── image_file_content_block_param.py │ │ │ ├── image_file_delta.py │ │ │ ├── image_file_delta_block.py │ │ │ ├── image_file_param.py │ │ │ ├── image_url.py │ │ │ ├── image_url_content_block.py │ │ │ ├── image_url_content_block_param.py │ │ │ ├── image_url_delta.py │ │ │ ├── image_url_delta_block.py │ │ │ ├── image_url_param.py │ │ │ ├── message.py │ │ │ ├── message_content.py │ │ │ ├── message_content_delta.py │ │ │ ├── message_content_part_param.py │ │ │ ├── message_create_params.py │ │ │ ├── message_deleted.py │ │ │ ├── message_delta.py │ │ │ ├── message_delta_event.py │ │ │ ├── message_list_params.py │ │ │ ├── message_update_params.py │ │ │ ├── refusal_content_block.py │ │ │ ├── refusal_delta_block.py │ │ │ ├── required_action_function_tool_call.py │ │ │ ├── run.py │ │ │ ├── run_create_params.py │ │ │ ├── run_list_params.py │ │ │ ├── run_status.py │ │ │ ├── run_submit_tool_outputs_params.py │ │ │ ├── run_update_params.py │ │ │ ├── runs/ │ │ │ │ ├── __init__.py │ │ │ │ ├── code_interpreter_logs.py │ │ │ │ ├── code_interpreter_output_image.py │ │ │ │ ├── code_interpreter_tool_call.py │ │ │ │ ├── code_interpreter_tool_call_delta.py │ │ │ │ ├── file_search_tool_call.py │ │ │ │ ├── file_search_tool_call_delta.py │ │ │ │ ├── function_tool_call.py │ │ │ │ ├── function_tool_call_delta.py │ │ │ │ ├── message_creation_step_details.py │ │ │ │ ├── run_step.py │ │ │ │ ├── run_step_delta.py │ │ │ │ ├── run_step_delta_event.py │ │ │ │ ├── run_step_delta_message_delta.py │ │ │ │ ├── run_step_include.py │ │ │ │ ├── step_list_params.py │ │ │ │ ├── step_retrieve_params.py │ │ │ │ ├── tool_call.py │ │ │ │ ├── tool_call_delta.py │ │ │ │ ├── tool_call_delta_object.py │ │ │ │ └── tool_calls_step_details.py │ │ │ ├── text.py │ │ │ ├── text_content_block.py │ │ │ ├── text_content_block_param.py │ │ │ ├── text_delta.py │ │ │ └── text_delta_block.py │ │ ├── chat/ │ │ │ ├── __init__.py │ │ │ ├── chat_completion.py │ │ │ ├── chat_completion_allowed_tool_choice_param.py │ │ │ ├── chat_completion_allowed_tools_param.py │ │ │ ├── chat_completion_assistant_message_param.py │ │ │ ├── chat_completion_audio.py │ │ │ ├── chat_completion_audio_param.py │ │ │ ├── chat_completion_chunk.py │ │ │ ├── chat_completion_content_part_image.py │ │ │ ├── chat_completion_content_part_image_param.py │ │ │ ├── chat_completion_content_part_input_audio_param.py │ │ │ ├── chat_completion_content_part_param.py │ │ │ ├── chat_completion_content_part_refusal_param.py │ │ │ ├── chat_completion_content_part_text.py │ │ │ ├── chat_completion_content_part_text_param.py │ │ │ ├── chat_completion_custom_tool_param.py │ │ │ ├── chat_completion_deleted.py │ │ │ ├── chat_completion_developer_message_param.py │ │ │ ├── chat_completion_function_call_option_param.py │ │ │ ├── chat_completion_function_message_param.py │ │ │ ├── chat_completion_function_tool.py │ │ │ ├── chat_completion_function_tool_param.py │ │ │ ├── chat_completion_message.py │ │ │ ├── chat_completion_message_custom_tool_call.py │ │ │ ├── chat_completion_message_custom_tool_call_param.py │ │ │ ├── chat_completion_message_function_tool_call.py │ │ │ ├── chat_completion_message_function_tool_call_param.py │ │ │ ├── chat_completion_message_param.py │ │ │ ├── chat_completion_message_tool_call.py │ │ │ ├── chat_completion_message_tool_call_param.py │ │ │ ├── chat_completion_message_tool_call_union_param.py │ │ │ ├── chat_completion_modality.py │ │ │ ├── chat_completion_named_tool_choice_custom_param.py │ │ │ ├── chat_completion_named_tool_choice_param.py │ │ │ ├── chat_completion_prediction_content_param.py │ │ │ ├── chat_completion_reasoning_effort.py │ │ │ ├── chat_completion_role.py │ │ │ ├── chat_completion_store_message.py │ │ │ ├── chat_completion_stream_options_param.py │ │ │ ├── chat_completion_system_message_param.py │ │ │ ├── chat_completion_token_logprob.py │ │ │ ├── chat_completion_tool_choice_option_param.py │ │ │ ├── chat_completion_tool_message_param.py │ │ │ ├── chat_completion_tool_param.py │ │ │ ├── chat_completion_tool_union_param.py │ │ │ ├── chat_completion_user_message_param.py │ │ │ ├── completion_create_params.py │ │ │ ├── completion_list_params.py │ │ │ ├── completion_update_params.py │ │ │ ├── completions/ │ │ │ │ ├── __init__.py │ │ │ │ └── message_list_params.py │ │ │ ├── parsed_chat_completion.py │ │ │ └── parsed_function_tool_call.py │ │ ├── chat_model.py │ │ ├── completion.py │ │ ├── completion_choice.py │ │ ├── completion_create_params.py │ │ ├── completion_usage.py │ │ ├── container_create_params.py │ │ ├── container_create_response.py │ │ ├── container_list_params.py │ │ ├── container_list_response.py │ │ ├── container_retrieve_response.py │ │ ├── containers/ │ │ │ ├── __init__.py │ │ │ ├── file_create_params.py │ │ │ ├── file_create_response.py │ │ │ ├── file_list_params.py │ │ │ ├── file_list_response.py │ │ │ ├── file_retrieve_response.py │ │ │ └── files/ │ │ │ └── __init__.py │ │ ├── conversations/ │ │ │ ├── __init__.py │ │ │ ├── computer_screenshot_content.py │ │ │ ├── conversation.py │ │ │ ├── conversation_create_params.py │ │ │ ├── conversation_deleted_resource.py │ │ │ ├── conversation_item.py │ │ │ ├── conversation_item_list.py │ │ │ ├── conversation_update_params.py │ │ │ ├── input_file_content.py │ │ │ ├── input_file_content_param.py │ │ │ ├── input_image_content.py │ │ │ ├── input_image_content_param.py │ │ │ ├── input_text_content.py │ │ │ ├── input_text_content_param.py │ │ │ ├── item_create_params.py │ │ │ ├── item_list_params.py │ │ │ ├── item_retrieve_params.py │ │ │ ├── message.py │ │ │ ├── output_text_content.py │ │ │ ├── output_text_content_param.py │ │ │ ├── refusal_content.py │ │ │ ├── refusal_content_param.py │ │ │ ├── summary_text_content.py │ │ │ └── text_content.py │ │ ├── create_embedding_response.py │ │ ├── deleted_skill.py │ │ ├── embedding.py │ │ ├── embedding_create_params.py │ │ ├── embedding_model.py │ │ ├── eval_create_params.py │ │ ├── eval_create_response.py │ │ ├── eval_custom_data_source_config.py │ │ ├── eval_delete_response.py │ │ ├── eval_list_params.py │ │ ├── eval_list_response.py │ │ ├── eval_retrieve_response.py │ │ ├── eval_stored_completions_data_source_config.py │ │ ├── eval_update_params.py │ │ ├── eval_update_response.py │ │ ├── evals/ │ │ │ ├── __init__.py │ │ │ ├── create_eval_completions_run_data_source.py │ │ │ ├── create_eval_completions_run_data_source_param.py │ │ │ ├── create_eval_jsonl_run_data_source.py │ │ │ ├── create_eval_jsonl_run_data_source_param.py │ │ │ ├── eval_api_error.py │ │ │ ├── run_cancel_response.py │ │ │ ├── run_create_params.py │ │ │ ├── run_create_response.py │ │ │ ├── run_delete_response.py │ │ │ ├── run_list_params.py │ │ │ ├── run_list_response.py │ │ │ ├── run_retrieve_response.py │ │ │ └── runs/ │ │ │ ├── __init__.py │ │ │ ├── output_item_list_params.py │ │ │ ├── output_item_list_response.py │ │ │ └── output_item_retrieve_response.py │ │ ├── file_chunking_strategy.py │ │ ├── file_chunking_strategy_param.py │ │ ├── file_content.py │ │ ├── file_create_params.py │ │ ├── file_deleted.py │ │ ├── file_list_params.py │ │ ├── file_object.py │ │ ├── file_purpose.py │ │ ├── fine_tuning/ │ │ │ ├── __init__.py │ │ │ ├── alpha/ │ │ │ │ ├── __init__.py │ │ │ │ ├── grader_run_params.py │ │ │ │ ├── grader_run_response.py │ │ │ │ ├── grader_validate_params.py │ │ │ │ └── grader_validate_response.py │ │ │ ├── checkpoints/ │ │ │ │ ├── __init__.py │ │ │ │ ├── permission_create_params.py │ │ │ │ ├── permission_create_response.py │ │ │ │ ├── permission_delete_response.py │ │ │ │ ├── permission_list_params.py │ │ │ │ ├── permission_list_response.py │ │ │ │ ├── permission_retrieve_params.py │ │ │ │ └── permission_retrieve_response.py │ │ │ ├── dpo_hyperparameters.py │ │ │ ├── dpo_hyperparameters_param.py │ │ │ ├── dpo_method.py │ │ │ ├── dpo_method_param.py │ │ │ ├── fine_tuning_job.py │ │ │ ├── fine_tuning_job_event.py │ │ │ ├── fine_tuning_job_integration.py │ │ │ ├── fine_tuning_job_wandb_integration.py │ │ │ ├── fine_tuning_job_wandb_integration_object.py │ │ │ ├── job_create_params.py │ │ │ ├── job_list_events_params.py │ │ │ ├── job_list_params.py │ │ │ ├── jobs/ │ │ │ │ ├── __init__.py │ │ │ │ ├── checkpoint_list_params.py │ │ │ │ └── fine_tuning_job_checkpoint.py │ │ │ ├── reinforcement_hyperparameters.py │ │ │ ├── reinforcement_hyperparameters_param.py │ │ │ ├── reinforcement_method.py │ │ │ ├── reinforcement_method_param.py │ │ │ ├── supervised_hyperparameters.py │ │ │ ├── supervised_hyperparameters_param.py │ │ │ ├── supervised_method.py │ │ │ └── supervised_method_param.py │ │ ├── graders/ │ │ │ ├── __init__.py │ │ │ ├── grader_inputs.py │ │ │ ├── grader_inputs_param.py │ │ │ ├── label_model_grader.py │ │ │ ├── label_model_grader_param.py │ │ │ ├── multi_grader.py │ │ │ ├── multi_grader_param.py │ │ │ ├── python_grader.py │ │ │ ├── python_grader_param.py │ │ │ ├── score_model_grader.py │ │ │ ├── score_model_grader_param.py │ │ │ ├── string_check_grader.py │ │ │ ├── string_check_grader_param.py │ │ │ ├── text_similarity_grader.py │ │ │ └── text_similarity_grader_param.py │ │ ├── image.py │ │ ├── image_create_variation_params.py │ │ ├── image_edit_completed_event.py │ │ ├── image_edit_params.py │ │ ├── image_edit_partial_image_event.py │ │ ├── image_edit_stream_event.py │ │ ├── image_gen_completed_event.py │ │ ├── image_gen_partial_image_event.py │ │ ├── image_gen_stream_event.py │ │ ├── image_generate_params.py │ │ ├── image_input_reference_param.py │ │ ├── image_model.py │ │ ├── images_response.py │ │ ├── model.py │ │ ├── model_deleted.py │ │ ├── moderation.py │ │ ├── moderation_create_params.py │ │ ├── moderation_create_response.py │ │ ├── moderation_image_url_input_param.py │ │ ├── moderation_model.py │ │ ├── moderation_multi_modal_input_param.py │ │ ├── moderation_text_input_param.py │ │ ├── other_file_chunking_strategy_object.py │ │ ├── realtime/ │ │ │ ├── __init__.py │ │ │ ├── audio_transcription.py │ │ │ ├── audio_transcription_param.py │ │ │ ├── call_accept_params.py │ │ │ ├── call_create_params.py │ │ │ ├── call_refer_params.py │ │ │ ├── call_reject_params.py │ │ │ ├── client_secret_create_params.py │ │ │ ├── client_secret_create_response.py │ │ │ ├── conversation_created_event.py │ │ │ ├── conversation_item.py │ │ │ ├── conversation_item_added.py │ │ │ ├── conversation_item_create_event.py │ │ │ ├── conversation_item_create_event_param.py │ │ │ ├── conversation_item_created_event.py │ │ │ ├── conversation_item_delete_event.py │ │ │ ├── conversation_item_delete_event_param.py │ │ │ ├── conversation_item_deleted_event.py │ │ │ ├── conversation_item_done.py │ │ │ ├── conversation_item_input_audio_transcription_completed_event.py │ │ │ ├── conversation_item_input_audio_transcription_delta_event.py │ │ │ ├── conversation_item_input_audio_transcription_failed_event.py │ │ │ ├── conversation_item_input_audio_transcription_segment.py │ │ │ ├── conversation_item_param.py │ │ │ ├── conversation_item_retrieve_event.py │ │ │ ├── conversation_item_retrieve_event_param.py │ │ │ ├── conversation_item_truncate_event.py │ │ │ ├── conversation_item_truncate_event_param.py │ │ │ ├── conversation_item_truncated_event.py │ │ │ ├── input_audio_buffer_append_event.py │ │ │ ├── input_audio_buffer_append_event_param.py │ │ │ ├── input_audio_buffer_clear_event.py │ │ │ ├── input_audio_buffer_clear_event_param.py │ │ │ ├── input_audio_buffer_cleared_event.py │ │ │ ├── input_audio_buffer_commit_event.py │ │ │ ├── input_audio_buffer_commit_event_param.py │ │ │ ├── input_audio_buffer_committed_event.py │ │ │ ├── input_audio_buffer_dtmf_event_received_event.py │ │ │ ├── input_audio_buffer_speech_started_event.py │ │ │ ├── input_audio_buffer_speech_stopped_event.py │ │ │ ├── input_audio_buffer_timeout_triggered.py │ │ │ ├── log_prob_properties.py │ │ │ ├── mcp_list_tools_completed.py │ │ │ ├── mcp_list_tools_failed.py │ │ │ ├── mcp_list_tools_in_progress.py │ │ │ ├── noise_reduction_type.py │ │ │ ├── output_audio_buffer_clear_event.py │ │ │ ├── output_audio_buffer_clear_event_param.py │ │ │ ├── rate_limits_updated_event.py │ │ │ ├── realtime_audio_config.py │ │ │ ├── realtime_audio_config_input.py │ │ │ ├── realtime_audio_config_input_param.py │ │ │ ├── realtime_audio_config_output.py │ │ │ ├── realtime_audio_config_output_param.py │ │ │ ├── realtime_audio_config_param.py │ │ │ ├── realtime_audio_formats.py │ │ │ ├── realtime_audio_formats_param.py │ │ │ ├── realtime_audio_input_turn_detection.py │ │ │ ├── realtime_audio_input_turn_detection_param.py │ │ │ ├── realtime_client_event.py │ │ │ ├── realtime_client_event_param.py │ │ │ ├── realtime_connect_params.py │ │ │ ├── realtime_conversation_item_assistant_message.py │ │ │ ├── realtime_conversation_item_assistant_message_param.py │ │ │ ├── realtime_conversation_item_function_call.py │ │ │ ├── realtime_conversation_item_function_call_output.py │ │ │ ├── realtime_conversation_item_function_call_output_param.py │ │ │ ├── realtime_conversation_item_function_call_param.py │ │ │ ├── realtime_conversation_item_system_message.py │ │ │ ├── realtime_conversation_item_system_message_param.py │ │ │ ├── realtime_conversation_item_user_message.py │ │ │ ├── realtime_conversation_item_user_message_param.py │ │ │ ├── realtime_error.py │ │ │ ├── realtime_error_event.py │ │ │ ├── realtime_function_tool.py │ │ │ ├── realtime_function_tool_param.py │ │ │ ├── realtime_mcp_approval_request.py │ │ │ ├── realtime_mcp_approval_request_param.py │ │ │ ├── realtime_mcp_approval_response.py │ │ │ ├── realtime_mcp_approval_response_param.py │ │ │ ├── realtime_mcp_list_tools.py │ │ │ ├── realtime_mcp_list_tools_param.py │ │ │ ├── realtime_mcp_protocol_error.py │ │ │ ├── realtime_mcp_protocol_error_param.py │ │ │ ├── realtime_mcp_tool_call.py │ │ │ ├── realtime_mcp_tool_call_param.py │ │ │ ├── realtime_mcp_tool_execution_error.py │ │ │ ├── realtime_mcp_tool_execution_error_param.py │ │ │ ├── realtime_mcphttp_error.py │ │ │ ├── realtime_mcphttp_error_param.py │ │ │ ├── realtime_response.py │ │ │ ├── realtime_response_create_audio_output.py │ │ │ ├── realtime_response_create_audio_output_param.py │ │ │ ├── realtime_response_create_mcp_tool.py │ │ │ ├── realtime_response_create_mcp_tool_param.py │ │ │ ├── realtime_response_create_params.py │ │ │ ├── realtime_response_create_params_param.py │ │ │ ├── realtime_response_status.py │ │ │ ├── realtime_response_usage.py │ │ │ ├── realtime_response_usage_input_token_details.py │ │ │ ├── realtime_response_usage_output_token_details.py │ │ │ ├── realtime_server_event.py │ │ │ ├── realtime_session_client_secret.py │ │ │ ├── realtime_session_create_request.py │ │ │ ├── realtime_session_create_request_param.py │ │ │ ├── realtime_session_create_response.py │ │ │ ├── realtime_tool_choice_config.py │ │ │ ├── realtime_tool_choice_config_param.py │ │ │ ├── realtime_tools_config.py │ │ │ ├── realtime_tools_config_param.py │ │ │ ├── realtime_tools_config_union.py │ │ │ ├── realtime_tools_config_union_param.py │ │ │ ├── realtime_tracing_config.py │ │ │ ├── realtime_tracing_config_param.py │ │ │ ├── realtime_transcription_session_audio.py │ │ │ ├── realtime_transcription_session_audio_input.py │ │ │ ├── realtime_transcription_session_audio_input_param.py │ │ │ ├── realtime_transcription_session_audio_input_turn_detection.py │ │ │ ├── realtime_transcription_session_audio_input_turn_detection_param.py │ │ │ ├── realtime_transcription_session_audio_param.py │ │ │ ├── realtime_transcription_session_create_request.py │ │ │ ├── realtime_transcription_session_create_request_param.py │ │ │ ├── realtime_transcription_session_create_response.py │ │ │ ├── realtime_transcription_session_turn_detection.py │ │ │ ├── realtime_truncation.py │ │ │ ├── realtime_truncation_param.py │ │ │ ├── realtime_truncation_retention_ratio.py │ │ │ ├── realtime_truncation_retention_ratio_param.py │ │ │ ├── response_audio_delta_event.py │ │ │ ├── response_audio_done_event.py │ │ │ ├── response_audio_transcript_delta_event.py │ │ │ ├── response_audio_transcript_done_event.py │ │ │ ├── response_cancel_event.py │ │ │ ├── response_cancel_event_param.py │ │ │ ├── response_content_part_added_event.py │ │ │ ├── response_content_part_done_event.py │ │ │ ├── response_create_event.py │ │ │ ├── response_create_event_param.py │ │ │ ├── response_created_event.py │ │ │ ├── response_done_event.py │ │ │ ├── response_function_call_arguments_delta_event.py │ │ │ ├── response_function_call_arguments_done_event.py │ │ │ ├── response_mcp_call_arguments_delta.py │ │ │ ├── response_mcp_call_arguments_done.py │ │ │ ├── response_mcp_call_completed.py │ │ │ ├── response_mcp_call_failed.py │ │ │ ├── response_mcp_call_in_progress.py │ │ │ ├── response_output_item_added_event.py │ │ │ ├── response_output_item_done_event.py │ │ │ ├── response_text_delta_event.py │ │ │ ├── response_text_done_event.py │ │ │ ├── session_created_event.py │ │ │ ├── session_update_event.py │ │ │ ├── session_update_event_param.py │ │ │ └── session_updated_event.py │ │ ├── responses/ │ │ │ ├── __init__.py │ │ │ ├── apply_patch_tool.py │ │ │ ├── apply_patch_tool_param.py │ │ │ ├── compacted_response.py │ │ │ ├── computer_action.py │ │ │ ├── computer_action_list.py │ │ │ ├── computer_action_list_param.py │ │ │ ├── computer_action_param.py │ │ │ ├── computer_tool.py │ │ │ ├── computer_tool_param.py │ │ │ ├── computer_use_preview_tool.py │ │ │ ├── computer_use_preview_tool_param.py │ │ │ ├── container_auto.py │ │ │ ├── container_auto_param.py │ │ │ ├── container_network_policy_allowlist.py │ │ │ ├── container_network_policy_allowlist_param.py │ │ │ ├── container_network_policy_disabled.py │ │ │ ├── container_network_policy_disabled_param.py │ │ │ ├── container_network_policy_domain_secret.py │ │ │ ├── container_network_policy_domain_secret_param.py │ │ │ ├── container_reference.py │ │ │ ├── container_reference_param.py │ │ │ ├── custom_tool.py │ │ │ ├── custom_tool_param.py │ │ │ ├── easy_input_message.py │ │ │ ├── easy_input_message_param.py │ │ │ ├── file_search_tool.py │ │ │ ├── file_search_tool_param.py │ │ │ ├── function_shell_tool.py │ │ │ ├── function_shell_tool_param.py │ │ │ ├── function_tool.py │ │ │ ├── function_tool_param.py │ │ │ ├── inline_skill.py │ │ │ ├── inline_skill_param.py │ │ │ ├── inline_skill_source.py │ │ │ ├── inline_skill_source_param.py │ │ │ ├── input_item_list_params.py │ │ │ ├── input_token_count_params.py │ │ │ ├── input_token_count_response.py │ │ │ ├── local_environment.py │ │ │ ├── local_environment_param.py │ │ │ ├── local_skill.py │ │ │ ├── local_skill_param.py │ │ │ ├── namespace_tool.py │ │ │ ├── namespace_tool_param.py │ │ │ ├── parsed_response.py │ │ │ ├── response.py │ │ │ ├── response_apply_patch_tool_call.py │ │ │ ├── response_apply_patch_tool_call_output.py │ │ │ ├── response_audio_delta_event.py │ │ │ ├── response_audio_done_event.py │ │ │ ├── response_audio_transcript_delta_event.py │ │ │ ├── response_audio_transcript_done_event.py │ │ │ ├── response_code_interpreter_call_code_delta_event.py │ │ │ ├── response_code_interpreter_call_code_done_event.py │ │ │ ├── response_code_interpreter_call_completed_event.py │ │ │ ├── response_code_interpreter_call_in_progress_event.py │ │ │ ├── response_code_interpreter_call_interpreting_event.py │ │ │ ├── response_code_interpreter_tool_call.py │ │ │ ├── response_code_interpreter_tool_call_param.py │ │ │ ├── response_compact_params.py │ │ │ ├── response_compaction_item.py │ │ │ ├── response_compaction_item_param.py │ │ │ ├── response_compaction_item_param_param.py │ │ │ ├── response_completed_event.py │ │ │ ├── response_computer_tool_call.py │ │ │ ├── response_computer_tool_call_output_item.py │ │ │ ├── response_computer_tool_call_output_screenshot.py │ │ │ ├── response_computer_tool_call_output_screenshot_param.py │ │ │ ├── response_computer_tool_call_param.py │ │ │ ├── response_container_reference.py │ │ │ ├── response_content_part_added_event.py │ │ │ ├── response_content_part_done_event.py │ │ │ ├── response_conversation_param.py │ │ │ ├── response_conversation_param_param.py │ │ │ ├── response_create_params.py │ │ │ ├── response_created_event.py │ │ │ ├── response_custom_tool_call.py │ │ │ ├── response_custom_tool_call_input_delta_event.py │ │ │ ├── response_custom_tool_call_input_done_event.py │ │ │ ├── response_custom_tool_call_output.py │ │ │ ├── response_custom_tool_call_output_param.py │ │ │ ├── response_custom_tool_call_param.py │ │ │ ├── response_error.py │ │ │ ├── response_error_event.py │ │ │ ├── response_failed_event.py │ │ │ ├── response_file_search_call_completed_event.py │ │ │ ├── response_file_search_call_in_progress_event.py │ │ │ ├── response_file_search_call_searching_event.py │ │ │ ├── response_file_search_tool_call.py │ │ │ ├── response_file_search_tool_call_param.py │ │ │ ├── response_format_text_config.py │ │ │ ├── response_format_text_config_param.py │ │ │ ├── response_format_text_json_schema_config.py │ │ │ ├── response_format_text_json_schema_config_param.py │ │ │ ├── response_function_call_arguments_delta_event.py │ │ │ ├── response_function_call_arguments_done_event.py │ │ │ ├── response_function_call_output_item.py │ │ │ ├── response_function_call_output_item_list.py │ │ │ ├── response_function_call_output_item_list_param.py │ │ │ ├── response_function_call_output_item_param.py │ │ │ ├── response_function_shell_call_output_content.py │ │ │ ├── response_function_shell_call_output_content_param.py │ │ │ ├── response_function_shell_tool_call.py │ │ │ ├── response_function_shell_tool_call_output.py │ │ │ ├── response_function_tool_call.py │ │ │ ├── response_function_tool_call_item.py │ │ │ ├── response_function_tool_call_output_item.py │ │ │ ├── response_function_tool_call_param.py │ │ │ ├── response_function_web_search.py │ │ │ ├── response_function_web_search_param.py │ │ │ ├── response_image_gen_call_completed_event.py │ │ │ ├── response_image_gen_call_generating_event.py │ │ │ ├── response_image_gen_call_in_progress_event.py │ │ │ ├── response_image_gen_call_partial_image_event.py │ │ │ ├── response_in_progress_event.py │ │ │ ├── response_includable.py │ │ │ ├── response_incomplete_event.py │ │ │ ├── response_input.py │ │ │ ├── response_input_audio.py │ │ │ ├── response_input_audio_param.py │ │ │ ├── response_input_content.py │ │ │ ├── response_input_content_param.py │ │ │ ├── response_input_file.py │ │ │ ├── response_input_file_content.py │ │ │ ├── response_input_file_content_param.py │ │ │ ├── response_input_file_param.py │ │ │ ├── response_input_image.py │ │ │ ├── response_input_image_content.py │ │ │ ├── response_input_image_content_param.py │ │ │ ├── response_input_image_param.py │ │ │ ├── response_input_item.py │ │ │ ├── response_input_item_param.py │ │ │ ├── response_input_message_content_list.py │ │ │ ├── response_input_message_content_list_param.py │ │ │ ├── response_input_message_item.py │ │ │ ├── response_input_param.py │ │ │ ├── response_input_text.py │ │ │ ├── response_input_text_content.py │ │ │ ├── response_input_text_content_param.py │ │ │ ├── response_input_text_param.py │ │ │ ├── response_item.py │ │ │ ├── response_item_list.py │ │ │ ├── response_local_environment.py │ │ │ ├── response_mcp_call_arguments_delta_event.py │ │ │ ├── response_mcp_call_arguments_done_event.py │ │ │ ├── response_mcp_call_completed_event.py │ │ │ ├── response_mcp_call_failed_event.py │ │ │ ├── response_mcp_call_in_progress_event.py │ │ │ ├── response_mcp_list_tools_completed_event.py │ │ │ ├── response_mcp_list_tools_failed_event.py │ │ │ ├── response_mcp_list_tools_in_progress_event.py │ │ │ ├── response_output_item.py │ │ │ ├── response_output_item_added_event.py │ │ │ ├── response_output_item_done_event.py │ │ │ ├── response_output_message.py │ │ │ ├── response_output_message_param.py │ │ │ ├── response_output_refusal.py │ │ │ ├── response_output_refusal_param.py │ │ │ ├── response_output_text.py │ │ │ ├── response_output_text_annotation_added_event.py │ │ │ ├── response_output_text_param.py │ │ │ ├── response_prompt.py │ │ │ ├── response_prompt_param.py │ │ │ ├── response_queued_event.py │ │ │ ├── response_reasoning_item.py │ │ │ ├── response_reasoning_item_param.py │ │ │ ├── response_reasoning_summary_part_added_event.py │ │ │ ├── response_reasoning_summary_part_done_event.py │ │ │ ├── response_reasoning_summary_text_delta_event.py │ │ │ ├── response_reasoning_summary_text_done_event.py │ │ │ ├── response_reasoning_text_delta_event.py │ │ │ ├── response_reasoning_text_done_event.py │ │ │ ├── response_refusal_delta_event.py │ │ │ ├── response_refusal_done_event.py │ │ │ ├── response_retrieve_params.py │ │ │ ├── response_status.py │ │ │ ├── response_stream_event.py │ │ │ ├── response_text_config.py │ │ │ ├── response_text_config_param.py │ │ │ ├── response_text_delta_event.py │ │ │ ├── response_text_done_event.py │ │ │ ├── response_tool_search_call.py │ │ │ ├── response_tool_search_output_item.py │ │ │ ├── response_tool_search_output_item_param.py │ │ │ ├── response_tool_search_output_item_param_param.py │ │ │ ├── response_usage.py │ │ │ ├── response_web_search_call_completed_event.py │ │ │ ├── response_web_search_call_in_progress_event.py │ │ │ ├── response_web_search_call_searching_event.py │ │ │ ├── responses_client_event.py │ │ │ ├── responses_client_event_param.py │ │ │ ├── responses_server_event.py │ │ │ ├── skill_reference.py │ │ │ ├── skill_reference_param.py │ │ │ ├── tool.py │ │ │ ├── tool_choice_allowed.py │ │ │ ├── tool_choice_allowed_param.py │ │ │ ├── tool_choice_apply_patch.py │ │ │ ├── tool_choice_apply_patch_param.py │ │ │ ├── tool_choice_custom.py │ │ │ ├── tool_choice_custom_param.py │ │ │ ├── tool_choice_function.py │ │ │ ├── tool_choice_function_param.py │ │ │ ├── tool_choice_mcp.py │ │ │ ├── tool_choice_mcp_param.py │ │ │ ├── tool_choice_options.py │ │ │ ├── tool_choice_shell.py │ │ │ ├── tool_choice_shell_param.py │ │ │ ├── tool_choice_types.py │ │ │ ├── tool_choice_types_param.py │ │ │ ├── tool_param.py │ │ │ ├── tool_search_tool.py │ │ │ ├── tool_search_tool_param.py │ │ │ ├── web_search_preview_tool.py │ │ │ ├── web_search_preview_tool_param.py │ │ │ ├── web_search_tool.py │ │ │ └── web_search_tool_param.py │ │ ├── shared/ │ │ │ ├── __init__.py │ │ │ ├── all_models.py │ │ │ ├── chat_model.py │ │ │ ├── comparison_filter.py │ │ │ ├── compound_filter.py │ │ │ ├── custom_tool_input_format.py │ │ │ ├── error_object.py │ │ │ ├── function_definition.py │ │ │ ├── function_parameters.py │ │ │ ├── metadata.py │ │ │ ├── reasoning.py │ │ │ ├── reasoning_effort.py │ │ │ ├── response_format_json_object.py │ │ │ ├── response_format_json_schema.py │ │ │ ├── response_format_text.py │ │ │ ├── response_format_text_grammar.py │ │ │ ├── response_format_text_python.py │ │ │ └── responses_model.py │ │ ├── shared_params/ │ │ │ ├── __init__.py │ │ │ ├── chat_model.py │ │ │ ├── comparison_filter.py │ │ │ ├── compound_filter.py │ │ │ ├── custom_tool_input_format.py │ │ │ ├── function_definition.py │ │ │ ├── function_parameters.py │ │ │ ├── metadata.py │ │ │ ├── reasoning.py │ │ │ ├── reasoning_effort.py │ │ │ ├── response_format_json_object.py │ │ │ ├── response_format_json_schema.py │ │ │ ├── response_format_text.py │ │ │ └── responses_model.py │ │ ├── skill.py │ │ ├── skill_create_params.py │ │ ├── skill_list.py │ │ ├── skill_list_params.py │ │ ├── skill_update_params.py │ │ ├── skills/ │ │ │ ├── __init__.py │ │ │ ├── deleted_skill_version.py │ │ │ ├── skill_version.py │ │ │ ├── skill_version_list.py │ │ │ ├── version_create_params.py │ │ │ ├── version_list_params.py │ │ │ └── versions/ │ │ │ └── __init__.py │ │ ├── static_file_chunking_strategy.py │ │ ├── static_file_chunking_strategy_object.py │ │ ├── static_file_chunking_strategy_object_param.py │ │ ├── static_file_chunking_strategy_param.py │ │ ├── upload.py │ │ ├── upload_complete_params.py │ │ ├── upload_create_params.py │ │ ├── uploads/ │ │ │ ├── __init__.py │ │ │ ├── part_create_params.py │ │ │ └── upload_part.py │ │ ├── vector_store.py │ │ ├── vector_store_create_params.py │ │ ├── vector_store_deleted.py │ │ ├── vector_store_list_params.py │ │ ├── vector_store_search_params.py │ │ ├── vector_store_search_response.py │ │ ├── vector_store_update_params.py │ │ ├── vector_stores/ │ │ │ ├── __init__.py │ │ │ ├── file_batch_create_params.py │ │ │ ├── file_batch_list_files_params.py │ │ │ ├── file_content_response.py │ │ │ ├── file_create_params.py │ │ │ ├── file_list_params.py │ │ │ ├── file_update_params.py │ │ │ ├── vector_store_file.py │ │ │ ├── vector_store_file_batch.py │ │ │ └── vector_store_file_deleted.py │ │ ├── video.py │ │ ├── video_create_character_params.py │ │ ├── video_create_character_response.py │ │ ├── video_create_error.py │ │ ├── video_create_params.py │ │ ├── video_delete_response.py │ │ ├── video_download_content_params.py │ │ ├── video_edit_params.py │ │ ├── video_extend_params.py │ │ ├── video_get_character_response.py │ │ ├── video_list_params.py │ │ ├── video_model.py │ │ ├── video_model_param.py │ │ ├── video_remix_params.py │ │ ├── video_seconds.py │ │ ├── video_size.py │ │ ├── webhooks/ │ │ │ ├── __init__.py │ │ │ ├── batch_cancelled_webhook_event.py │ │ │ ├── batch_completed_webhook_event.py │ │ │ ├── batch_expired_webhook_event.py │ │ │ ├── batch_failed_webhook_event.py │ │ │ ├── eval_run_canceled_webhook_event.py │ │ │ ├── eval_run_failed_webhook_event.py │ │ │ ├── eval_run_succeeded_webhook_event.py │ │ │ ├── fine_tuning_job_cancelled_webhook_event.py │ │ │ ├── fine_tuning_job_failed_webhook_event.py │ │ │ ├── fine_tuning_job_succeeded_webhook_event.py │ │ │ ├── realtime_call_incoming_webhook_event.py │ │ │ ├── response_cancelled_webhook_event.py │ │ │ ├── response_completed_webhook_event.py │ │ │ ├── response_failed_webhook_event.py │ │ │ ├── response_incomplete_webhook_event.py │ │ │ └── unwrap_webhook_event.py │ │ └── websocket_connection_options.py │ └── version.py └── tests/ ├── __init__.py ├── api_resources/ │ ├── __init__.py │ ├── audio/ │ │ ├── __init__.py │ │ ├── test_speech.py │ │ ├── test_transcriptions.py │ │ └── test_translations.py │ ├── beta/ │ │ ├── __init__.py │ │ ├── chatkit/ │ │ │ ├── __init__.py │ │ │ ├── test_sessions.py │ │ │ └── test_threads.py │ │ ├── test_assistants.py │ │ ├── test_realtime.py │ │ ├── test_threads.py │ │ └── threads/ │ │ ├── __init__.py │ │ ├── runs/ │ │ │ ├── __init__.py │ │ │ └── test_steps.py │ │ ├── test_messages.py │ │ └── test_runs.py │ ├── chat/ │ │ ├── __init__.py │ │ ├── completions/ │ │ │ ├── __init__.py │ │ │ └── test_messages.py │ │ └── test_completions.py │ ├── containers/ │ │ ├── __init__.py │ │ ├── files/ │ │ │ ├── __init__.py │ │ │ └── test_content.py │ │ └── test_files.py │ ├── conversations/ │ │ ├── __init__.py │ │ └── test_items.py │ ├── evals/ │ │ ├── __init__.py │ │ ├── runs/ │ │ │ ├── __init__.py │ │ │ └── test_output_items.py │ │ └── test_runs.py │ ├── fine_tuning/ │ │ ├── __init__.py │ │ ├── alpha/ │ │ │ ├── __init__.py │ │ │ └── test_graders.py │ │ ├── checkpoints/ │ │ │ ├── __init__.py │ │ │ └── test_permissions.py │ │ ├── jobs/ │ │ │ ├── __init__.py │ │ │ └── test_checkpoints.py │ │ └── test_jobs.py │ ├── realtime/ │ │ ├── __init__.py │ │ ├── test_calls.py │ │ └── test_client_secrets.py │ ├── responses/ │ │ ├── __init__.py │ │ ├── test_input_items.py │ │ └── test_input_tokens.py │ ├── skills/ │ │ ├── __init__.py │ │ ├── test_content.py │ │ ├── test_versions.py │ │ └── versions/ │ │ ├── __init__.py │ │ └── test_content.py │ ├── test_batches.py │ ├── test_completions.py │ ├── test_containers.py │ ├── test_conversations.py │ ├── test_embeddings.py │ ├── test_evals.py │ ├── test_files.py │ ├── test_images.py │ ├── test_models.py │ ├── test_moderations.py │ ├── test_realtime.py │ ├── test_responses.py │ ├── test_skills.py │ ├── test_uploads.py │ ├── test_vector_stores.py │ ├── test_videos.py │ ├── test_webhooks.py │ ├── uploads/ │ │ ├── __init__.py │ │ └── test_parts.py │ ├── vector_stores/ │ │ ├── __init__.py │ │ ├── test_file_batches.py │ │ └── test_files.py │ └── webhooks/ │ └── __init__.py ├── compat/ │ └── test_tool_param.py ├── conftest.py ├── lib/ │ ├── __init__.py │ ├── chat/ │ │ ├── __init__.py │ │ ├── test_completions.py │ │ └── test_completions_streaming.py │ ├── responses/ │ │ ├── __init__.py │ │ └── test_responses.py │ ├── schema_types/ │ │ └── query.py │ ├── snapshots.py │ ├── test_assistants.py │ ├── test_audio.py │ ├── test_azure.py │ ├── test_old_api.py │ ├── test_pydantic.py │ └── utils.py ├── sample_file.txt ├── test_client.py ├── test_deepcopy.py ├── test_extract_files.py ├── test_files.py ├── test_legacy_response.py ├── test_models.py ├── test_module_client.py ├── test_qs.py ├── test_required_args.py ├── test_response.py ├── test_streaming.py ├── test_transform.py ├── test_utils/ │ ├── test_datetime_parse.py │ ├── test_json.py │ ├── test_logging.py │ ├── test_proxy.py │ └── test_typing.py ├── test_websocket_connection_options.py └── utils.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .devcontainer/Dockerfile ================================================ ARG VARIANT="3.9" FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT} USER vscode RUN curl -sSf https://rye.astral.sh/get | RYE_VERSION="0.44.0" RYE_INSTALL_OPTION="--yes" bash ENV PATH=/home/vscode/.rye/shims:$PATH RUN echo "[[ -d .venv ]] && source .venv/bin/activate || export PATH=\$PATH" >> /home/vscode/.bashrc ================================================ FILE: .devcontainer/devcontainer.json ================================================ // For format details, see https://aka.ms/devcontainer.json. For config options, see the // README at: https://github.com/devcontainers/templates/tree/main/src/debian { "name": "Debian", "build": { "dockerfile": "Dockerfile", "context": ".." }, "postStartCommand": "rye sync --all-features", "customizations": { "vscode": { "extensions": [ "ms-python.python" ], "settings": { "terminal.integrated.shell.linux": "/bin/bash", "python.pythonPath": ".venv/bin/python", "python.defaultInterpreterPath": ".venv/bin/python", "python.typeChecking": "basic", "terminal.integrated.env.linux": { "PATH": "/home/vscode/.rye/shims:${env:PATH}" } } } }, "features": { "ghcr.io/devcontainers/features/node:1": {} } // Features to add to the dev container. More info: https://containers.dev/features. // "features": {}, // Use 'forwardPorts' to make a list of ports inside the container available locally. // "forwardPorts": [], // Configure tool-specific properties. // "customizations": {}, // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. // "remoteUser": "root" } ================================================ FILE: .github/CODEOWNERS ================================================ # This file is used to automatically assign reviewers to PRs # For more information see: https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners * @openai/sdks-team ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.yml ================================================ name: Bug report description: Report an issue or bug with this library labels: ['bug'] body: - type: markdown attributes: value: | Thanks for taking the time to fill out this bug report! - type: checkboxes id: non_api attributes: label: Confirm this is an issue with the Python library and not an underlying OpenAI API description: Issues with the underlying OpenAI API should be reported on our [Developer Community](https://community.openai.com/c/api/7) options: - label: This is an issue with the Python library required: true - type: textarea id: what-happened attributes: label: Describe the bug description: A clear and concise description of what the bug is, and any additional context. placeholder: Tell us what you see! validations: required: true - type: textarea id: repro-steps attributes: label: To Reproduce description: Steps to reproduce the behavior. placeholder: | 1. Fetch a '...' 2. Update the '....' 3. See error validations: required: true - type: textarea id: code-snippets attributes: label: Code snippets description: If applicable, add code snippets to help explain your problem. render: Python validations: required: false - type: input id: os attributes: label: OS placeholder: macOS validations: required: true - type: input id: language-version attributes: label: Python version placeholder: Python v3.11.4 validations: required: true - type: input id: lib-version attributes: label: Library version placeholder: openai v1.0.1 validations: required: true ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false contact_links: - name: OpenAI support url: https://help.openai.com/ about: | Please only file issues here that you believe represent actual bugs or feature requests for the OpenAI Python library. If you're having general trouble with the OpenAI API, please visit our help center to get support. ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.yml ================================================ name: Feature request description: Suggest an idea for this library labels: ['feature-request'] body: - type: markdown attributes: value: | Thanks for taking the time to fill out this feature request! - type: checkboxes id: non_api attributes: label: Confirm this is a feature request for the Python library and not the underlying OpenAI API. description: Feature requests for the underlying OpenAI API should be reported on our [Developer Community](https://community.openai.com/c/api/7) options: - label: This is a feature request for the Python library required: true - type: textarea id: feature attributes: label: Describe the feature or improvement you're requesting description: A clear and concise description of what you want to happen. validations: required: true - type: textarea id: context attributes: label: Additional context description: Add any other context about the feature request here. ================================================ FILE: .github/pull_request_template.md ================================================ - [ ] I understand that this repository is auto-generated and my pull request may not be merged ## Changes being requested ## Additional context & links ================================================ FILE: .github/workflows/ci.yml ================================================ name: CI on: push: branches: - '**' - '!integrated/**' - '!stl-preview-head/**' - '!stl-preview-base/**' - '!generated' - '!codegen/**' - 'codegen/stl/**' pull_request: branches-ignore: - 'stl-preview-head/**' - 'stl-preview-base/**' jobs: lint: timeout-minutes: 10 name: lint runs-on: ${{ github.repository == 'stainless-sdks/openai-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - uses: actions/checkout@v6 - name: Install Rye run: | curl -sSf https://rye.astral.sh/get | bash echo "$HOME/.rye/shims" >> $GITHUB_PATH env: RYE_VERSION: '0.44.0' RYE_INSTALL_OPTION: '--yes' - name: Install dependencies run: rye sync --all-features - name: Run lints run: ./scripts/lint build: if: github.event_name == 'push' || github.event.pull_request.head.repo.fork timeout-minutes: 10 name: build permissions: contents: read id-token: write runs-on: ${{ github.repository == 'stainless-sdks/openai-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} steps: - uses: actions/checkout@v6 - name: Install Rye run: | curl -sSf https://rye.astral.sh/get | bash echo "$HOME/.rye/shims" >> $GITHUB_PATH env: RYE_VERSION: '0.44.0' RYE_INSTALL_OPTION: '--yes' - name: Install dependencies run: rye sync --all-features - name: Run build run: rye build - name: Get GitHub OIDC Token if: |- github.repository == 'stainless-sdks/openai-python' && !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc uses: actions/github-script@v8 with: script: core.setOutput('github_token', await core.getIDToken()); - name: Upload tarball if: |- github.repository == 'stainless-sdks/openai-python' && !startsWith(github.ref, 'refs/heads/stl/') env: URL: https://pkg.stainless.com/s AUTH: ${{ steps.github-oidc.outputs.github_token }} SHA: ${{ github.sha }} run: ./scripts/utils/upload-artifact.sh test: timeout-minutes: 10 name: test runs-on: ${{ github.repository == 'stainless-sdks/openai-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - uses: actions/checkout@v6 - name: Install Rye run: | curl -sSf https://rye.astral.sh/get | bash echo "$HOME/.rye/shims" >> $GITHUB_PATH env: RYE_VERSION: '0.44.0' RYE_INSTALL_OPTION: '--yes' - name: Bootstrap run: ./scripts/bootstrap - name: Run tests run: ./scripts/test examples: timeout-minutes: 10 name: examples runs-on: ${{ github.repository == 'stainless-sdks/openai-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.repository == 'openai/openai-python' && (github.event_name == 'push' || github.event.pull_request.head.repo.fork) steps: - uses: actions/checkout@v6 - name: Install Rye run: | curl -sSf https://rye.astral.sh/get | bash echo "$HOME/.rye/shims" >> $GITHUB_PATH env: RYE_VERSION: '0.44.0' RYE_INSTALL_OPTION: '--yes' - name: Install dependencies run: | rye sync --all-features - env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} run: | rye run python examples/demo.py - env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} run: | rye run python examples/async_demo.py ================================================ FILE: .github/workflows/create-releases.yml ================================================ name: Create releases on: schedule: - cron: '0 5 * * *' # every day at 5am UTC push: branches: - main jobs: release: name: release if: github.ref == 'refs/heads/main' && github.repository == 'openai/openai-python' runs-on: ubuntu-latest environment: publish steps: - uses: actions/checkout@v6 - uses: stainless-api/trigger-release-please@v1 id: release with: repo: ${{ github.event.repository.full_name }} stainless-api-key: ${{ secrets.STAINLESS_API_KEY }} - name: Install Rye if: ${{ steps.release.outputs.releases_created }} run: | curl -sSf https://rye.astral.sh/get | bash echo "$HOME/.rye/shims" >> $GITHUB_PATH env: RYE_VERSION: '0.44.0' RYE_INSTALL_OPTION: '--yes' - name: Publish to PyPI if: ${{ steps.release.outputs.releases_created }} run: | bash ./bin/publish-pypi env: PYPI_TOKEN: ${{ secrets.OPENAI_PYPI_TOKEN || secrets.PYPI_TOKEN }} ================================================ FILE: .github/workflows/detect-breaking-changes.yml ================================================ name: CI on: pull_request: branches: - main - next jobs: detect_breaking_changes: runs-on: 'ubuntu-latest' name: detect-breaking-changes if: github.repository == 'openai/openai-python' steps: - name: Calculate fetch-depth run: | echo "FETCH_DEPTH=$(expr ${{ github.event.pull_request.commits }} + 1)" >> $GITHUB_ENV - uses: actions/checkout@v6 with: # Ensure we can check out the pull request base in the script below. fetch-depth: ${{ env.FETCH_DEPTH }} - name: Install Rye run: | curl -sSf https://rye.astral.sh/get | bash echo "$HOME/.rye/shims" >> $GITHUB_PATH env: RYE_VERSION: '0.44.0' RYE_INSTALL_OPTION: '--yes' - name: Install dependencies run: | rye sync --all-features - name: Detect removed symbols run: | rye run python scripts/detect-breaking-changes.py "${{ github.event.pull_request.base.sha }}" - name: Detect breaking changes run: | test -f ./scripts/detect-breaking-changes || { echo "Missing scripts/detect-breaking-changes"; exit 1; } ./scripts/detect-breaking-changes ${{ github.event.pull_request.base.sha }} agents_sdk: runs-on: 'ubuntu-latest' name: Detect Agents SDK regressions if: github.repository == 'openai/openai-python' steps: # Setup this sdk - uses: actions/checkout@v4 with: path: openai-python - name: Install Rye working-directory: openai-python run: | curl -sSf https://rye.astral.sh/get | bash echo "$HOME/.rye/shims" >> $GITHUB_PATH env: RYE_VERSION: '0.44.0' RYE_INSTALL_OPTION: '--yes' - name: Install dependencies working-directory: openai-python run: | rye sync --all-features # Setup the agents lib - uses: actions/checkout@v4 with: repository: openai/openai-agents-python path: openai-agents-python - name: Setup uv uses: astral-sh/setup-uv@v5 with: enable-cache: true - name: Link to local SDK working-directory: openai-agents-python run: uv add ../openai-python - name: Install dependencies working-directory: openai-agents-python run: make sync - name: Run integration type checks working-directory: openai-agents-python run: make mypy ================================================ FILE: .github/workflows/publish-pypi.yml ================================================ # workflow for re-running publishing to PyPI in case it fails for some reason # you can run this workflow by navigating to https://www.github.com/openai/openai-python/actions/workflows/publish-pypi.yml name: Publish PyPI on: workflow_dispatch: jobs: publish: name: publish runs-on: ubuntu-latest environment: publish steps: - uses: actions/checkout@v6 - name: Install Rye run: | curl -sSf https://rye.astral.sh/get | bash echo "$HOME/.rye/shims" >> $GITHUB_PATH env: RYE_VERSION: '0.44.0' RYE_INSTALL_OPTION: '--yes' - name: Publish to PyPI run: | bash ./bin/publish-pypi env: PYPI_TOKEN: ${{ secrets.OPENAI_PYPI_TOKEN || secrets.PYPI_TOKEN }} ================================================ FILE: .github/workflows/release-doctor.yml ================================================ name: Release Doctor on: push: branches: - main workflow_dispatch: jobs: release_doctor: name: release doctor runs-on: ubuntu-latest environment: publish if: github.repository == 'openai/openai-python' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - uses: actions/checkout@v6 - name: Check release environment run: | bash ./bin/check-release-environment env: STAINLESS_API_KEY: ${{ secrets.STAINLESS_API_KEY }} PYPI_TOKEN: ${{ secrets.OPENAI_PYPI_TOKEN || secrets.PYPI_TOKEN }} ================================================ FILE: .gitignore ================================================ .prism.log _dev __pycache__ .mypy_cache dist .venv .idea .env .envrc codegen.log Brewfile.lock.json .DS_Store examples/*.mp3 ================================================ FILE: .inline-snapshot/external/.gitignore ================================================ # ignore all snapshots which are not refered in the source *-new.* ================================================ FILE: .python-version ================================================ 3.9.18 ================================================ FILE: .release-please-manifest.json ================================================ { ".": "2.29.0" } ================================================ FILE: .stats.yml ================================================ configured_endpoints: 152 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-55ef7034334e938c30656a404ce5e21466103be87542a796425346299f450404.yml openapi_spec_hash: 4a5bfd2ee4ad47f5b7cf6f1ad08d5d7f config_hash: 96fbf82cf74a44ccd513f5acf0956ffd ================================================ FILE: .vscode/settings.json ================================================ { "python.analysis.importFormat": "relative", } ================================================ FILE: Brewfile ================================================ brew "rye" ================================================ FILE: CHANGELOG.md ================================================ # Changelog ## 2.29.0 (2026-03-17) Full Changelog: [v2.28.0...v2.29.0](https://github.com/openai/openai-python/compare/v2.28.0...v2.29.0) ### Features * **api:** 5.4 nano and mini model slugs ([3b45666](https://github.com/openai/openai-python/commit/3b456661f77ca3196aceb5ab3350664a63481114)) * **api:** add /v1/videos endpoint to batches create method ([c0e7a16](https://github.com/openai/openai-python/commit/c0e7a161a996854021e9eb69ea2a60ca0d08047f)) * **api:** add defer_loading field to ToolFunction ([3167595](https://github.com/openai/openai-python/commit/3167595432bdda2f90721901d30ad316db49323e)) * **api:** add in and nin operators to ComparisonFilter type ([664f02b](https://github.com/openai/openai-python/commit/664f02b051af84e1ca3fa313981ec72fdea269b3)) ### Bug Fixes * **deps:** bump minimum typing-extensions version ([a2fb2ca](https://github.com/openai/openai-python/commit/a2fb2ca55142c6658a18be7bd1392a01f5a83f35)) * **pydantic:** do not pass `by_alias` unless set ([8ebe8fb](https://github.com/openai/openai-python/commit/8ebe8fbcb011c6a005a715cae50c6400a8596ee0)) ### Chores * **internal:** tweak CI branches ([96ccc3c](https://github.com/openai/openai-python/commit/96ccc3cca35645fd3140f99b0fc8e55545065212)) ## 2.28.0 (2026-03-13) Full Changelog: [v2.27.0...v2.28.0](https://github.com/openai/openai-python/compare/v2.27.0...v2.28.0) ### Features * **api:** custom voices ([50dc060](https://github.com/openai/openai-python/commit/50dc060b55767615419219ef567d31210517e613)) ## 2.27.0 (2026-03-13) Full Changelog: [v2.26.0...v2.27.0](https://github.com/openai/openai-python/compare/v2.26.0...v2.27.0) ### Features * **api:** api update ([60ab24a](https://github.com/openai/openai-python/commit/60ab24ae722a7fa280eb4b2273da4ded1f930231)) * **api:** manual updates ([b244b09](https://github.com/openai/openai-python/commit/b244b0946045aaa0dbfa8c0ce5164b64e1156834)) * **api:** manual updates ([d806635](https://github.com/openai/openai-python/commit/d806635081a736cc81344bf1e62b57956a88d093)) * **api:** sora api improvements: character api, video extensions/edits, higher resolution exports. ([58b70d3](https://github.com/openai/openai-python/commit/58b70d304a4b2cf70eae4db4b448d439fc8b8ba3)) ### Bug Fixes * **api:** repair merged videos resource ([742d8ee](https://github.com/openai/openai-python/commit/742d8ee1f969ee1bbb39ba9d799dcd5c480d8ddb)) ### Chores * **internal:** codegen related update ([4e6498e](https://github.com/openai/openai-python/commit/4e6498e2d222dd35d76bb397ba976ff53c852e12)) * **internal:** codegen related update ([93af129](https://github.com/openai/openai-python/commit/93af129e8919de6d3aee19329c8bdef0532bd20a)) * match http protocol with ws protocol instead of wss ([026f9de](https://github.com/openai/openai-python/commit/026f9de35d2aa74f35c91261eb5ea43d4ab1b8ba)) * use proper capitalization for WebSockets ([a2f9b07](https://github.com/openai/openai-python/commit/a2f9b0722597627e8d01aa05c27a52015072726b)) ## 2.26.0 (2026-03-05) Full Changelog: [v2.25.0...v2.26.0](https://github.com/openai/openai-python/compare/v2.25.0...v2.26.0) ### Features * **api:** The GA ComputerTool now uses the CompuerTool class. The 'computer_use_preview' tool is moved to ComputerUsePreview ([78f5b3c](https://github.com/openai/openai-python/commit/78f5b3c287b71ed6fbeb71fb6b5c0366db704cd2)) ## 2.25.0 (2026-03-05) Full Changelog: [v2.24.0...v2.25.0](https://github.com/openai/openai-python/compare/v2.24.0...v2.25.0) ### Features * **api:** gpt-5.4, tool search tool, and new computer tool ([6b2043f](https://github.com/openai/openai-python/commit/6b2043f3d63058f5582eab7a7705b30a3d5536f0)) * **api:** remove prompt_cache_key param from responses, phase field from message types ([44fb382](https://github.com/openai/openai-python/commit/44fb382698872d98d5f72c880b47846c7b594f4f)) ### Bug Fixes * **api:** internal schema fixes ([0c0f970](https://github.com/openai/openai-python/commit/0c0f970cbd164131bf06f7ab38f170bbcb323683)) * **api:** manual updates ([9fc323f](https://github.com/openai/openai-python/commit/9fc323f4da6cfca9de194e12c1486a3cd1bfa4b5)) * **api:** readd phase ([1b27b5a](https://github.com/openai/openai-python/commit/1b27b5a834f5cb75f80c597259d0df0352ba83bd)) ### Chores * **internal:** codegen related update ([bdb837d](https://github.com/openai/openai-python/commit/bdb837d2c1d2a161cc4b22ef26e9e8446d5dc2a3)) * **internal:** codegen related update ([b1de941](https://github.com/openai/openai-python/commit/b1de9419a68fd6fb97a63f415fb3d1e5851582cb)) * **internal:** reduce warnings ([7cdbd06](https://github.com/openai/openai-python/commit/7cdbd06d3ca41af64d616b4b4bb61226cc38b662)) ## 2.24.0 (2026-02-24) Full Changelog: [v2.23.0...v2.24.0](https://github.com/openai/openai-python/compare/v2.23.0...v2.24.0) ### Features * **api:** add phase ([391deb9](https://github.com/openai/openai-python/commit/391deb99f6a92e51bffb25efd8dfe367d144bb9d)) ### Bug Fixes * **api:** fix phase enum ([42ebf7c](https://github.com/openai/openai-python/commit/42ebf7c30b7e27a175c0d75fcf42c8dc858e56d6)) * **api:** phase docs ([7ddc61c](https://github.com/openai/openai-python/commit/7ddc61cd0f7825d5e7f3a10daf809135511d8d20)) ### Chores * **internal:** make `test_proxy_environment_variables` more resilient to env ([65af8fd](https://github.com/openai/openai-python/commit/65af8fd8550e99236e3f4dcb035312441788157a)) * **internal:** refactor sse event parsing ([2344600](https://github.com/openai/openai-python/commit/23446008f06fb474d8c75d14a1bce26f4c5b95d8)) ## 2.23.0 (2026-02-24) Full Changelog: [v2.22.0...v2.23.0](https://github.com/openai/openai-python/compare/v2.22.0...v2.23.0) ### Features * **api:** add gpt-realtime-1.5 and gpt-audio-1.5 model options to realtime calls ([3300b61](https://github.com/openai/openai-python/commit/3300b61e1d5a34c9d28ec9cebbebd0de1fa93aa6)) ### Chores * **internal:** make `test_proxy_environment_variables` more resilient ([6b441e2](https://github.com/openai/openai-python/commit/6b441e2c43df60a773f62308e918d76b8eb3c4d3)) ## 2.22.0 (2026-02-23) Full Changelog: [v2.21.0...v2.22.0](https://github.com/openai/openai-python/compare/v2.21.0...v2.22.0) ### Features * **api:** websockets for responses api ([c01f6fb](https://github.com/openai/openai-python/commit/c01f6fb0d55b7454f73c4904ea7a1954553085dc)) ### Chores * **internal:** add request options to SSE classes ([cdb4315](https://github.com/openai/openai-python/commit/cdb4315ee29d5260bb373625d74cb523b4e3859c)) * update mock server docs ([91f4da8](https://github.com/openai/openai-python/commit/91f4da80ec3dba5d3566961560dfd6feb9c2feb0)) ### Documentation * **api:** add batch size limit to file_batches parameter descriptions ([16ae76a](https://github.com/openai/openai-python/commit/16ae76a20a47f94c91ee2ca0b2ada274633abab3)) * **api:** enhance method descriptions across audio, chat, realtime, skills, uploads, videos ([21f9e5a](https://github.com/openai/openai-python/commit/21f9e5aaf6ae27f0235fddb3ffa30fe73337f59b)) * **api:** update safety_identifier documentation in chat completions and responses ([d74bfff](https://github.com/openai/openai-python/commit/d74bfff62c1c2b32d4dc88fd47ae7b1b2a962017)) ## 2.21.0 (2026-02-13) Full Changelog: [v2.20.0...v2.21.0](https://github.com/openai/openai-python/compare/v2.20.0...v2.21.0) ### Features * **api:** container network_policy and skills ([d19de2e](https://github.com/openai/openai-python/commit/d19de2ee5c74413f9dc52684b650df1898dee82b)) ### Bug Fixes * **structured outputs:** resolve memory leak in parse methods ([#2860](https://github.com/openai/openai-python/issues/2860)) ([6dcbe21](https://github.com/openai/openai-python/commit/6dcbe211f12f8470db542a5cb95724cb933786dd)) * **webhooks:** preserve method visibility for compatibility checks ([44a8936](https://github.com/openai/openai-python/commit/44a8936d580b770f23fae79659101a27eadafad6)) ### Chores * **internal:** fix lint error on Python 3.14 ([534f215](https://github.com/openai/openai-python/commit/534f215941f504443d63509e872409a0b1236452)) ### Documentation * split `api.md` by standalone resources ([96e41b3](https://github.com/openai/openai-python/commit/96e41b398a110212ddec71436b2439343bea87d4)) * update comment ([63def23](https://github.com/openai/openai-python/commit/63def23b7acd5c6dacf03337fe1bd08439d1dba8)) ## 2.20.0 (2026-02-10) Full Changelog: [v2.19.0...v2.20.0](https://github.com/openai/openai-python/compare/v2.19.0...v2.20.0) ### Features * **api:** support for images in batch api ([28edb6e](https://github.com/openai/openai-python/commit/28edb6e1b7eb30dbb7be49979cee7882e8889264)) ## 2.19.0 (2026-02-10) Full Changelog: [v2.18.0...v2.19.0](https://github.com/openai/openai-python/compare/v2.18.0...v2.19.0) ### Features * **api:** skills and hosted shell ([27fdf68](https://github.com/openai/openai-python/commit/27fdf6820655b5994e3c1eddb3c8d9344a8be744)) ### Chores * **internal:** bump dependencies ([fae10fd](https://github.com/openai/openai-python/commit/fae10fd6e936a044f8393a454a39906aa325a893)) ## 2.18.0 (2026-02-09) Full Changelog: [v2.17.0...v2.18.0](https://github.com/openai/openai-python/compare/v2.17.0...v2.18.0) ### Features * **api:** add context_management to responses ([137e992](https://github.com/openai/openai-python/commit/137e992b80956401d1867274fa7a0969edfdba54)) * **api:** responses context_management ([c3bd017](https://github.com/openai/openai-python/commit/c3bd017318347af0a0105a7e975c8d91e22f7941)) ## 2.17.0 (2026-02-05) Full Changelog: [v2.16.0...v2.17.0](https://github.com/openai/openai-python/compare/v2.16.0...v2.17.0) ### Features * **api:** add shell_call_output status field ([1bbaf88](https://github.com/openai/openai-python/commit/1bbaf8865000b338c24c9fdd5e985183feaca10f)) * **api:** image generation actions for responses; ResponseFunctionCallArgumentsDoneEvent.name ([7d96513](https://github.com/openai/openai-python/commit/7d965135f93f41b0c3dbf3dc9f01796bd9645b6c)) * **client:** add custom JSON encoder for extended type support ([9f43c8b](https://github.com/openai/openai-python/commit/9f43c8b1a1641db2336cc6d0ec0c6dc470a89103)) ### Bug Fixes * **client:** undo change to web search Find action ([8f14eb0](https://github.com/openai/openai-python/commit/8f14eb0a74363fdfc648c5cd5c6d34a85b938d3c)) * **client:** update type for `find_in_page` action ([ec54dde](https://github.com/openai/openai-python/commit/ec54ddeb357e49edd81cc3fe53d549c297e59a07)) ## 2.16.0 (2026-01-27) Full Changelog: [v2.15.0...v2.16.0](https://github.com/openai/openai-python/compare/v2.15.0...v2.16.0) ### Features * **api:** api update ([b97f9f2](https://github.com/openai/openai-python/commit/b97f9f26b9c46ca4519130e60a8bf12ad8d52bf3)) * **api:** api updates ([9debcc0](https://github.com/openai/openai-python/commit/9debcc02370f5b76a6a609ded18fbf8dea87b9cb)) * **client:** add support for binary request streaming ([49561d8](https://github.com/openai/openai-python/commit/49561d88279628bc400d1b09aa98765b67018ef1)) ### Bug Fixes * **api:** mark assistants as deprecated ([0419cbc](https://github.com/openai/openai-python/commit/0419cbcbf1021131c7492321436ed01ca4337835)) ### Chores * **ci:** upgrade `actions/github-script` ([5139f13](https://github.com/openai/openai-python/commit/5139f13ef35e64dadc65f2ba2bab736977985769)) * **internal:** update `actions/checkout` version ([f276714](https://github.com/openai/openai-python/commit/f2767144c11833070c0579063ed33918089b4617)) ### Documentation * **examples:** update Azure Realtime sample to use v1 API ([#2829](https://github.com/openai/openai-python/issues/2829)) ([3b31981](https://github.com/openai/openai-python/commit/3b319819544d629c5b8c206b8b1f6ec6328c6136)) ## 2.15.0 (2026-01-09) Full Changelog: [v2.14.0...v2.15.0](https://github.com/openai/openai-python/compare/v2.14.0...v2.15.0) ### Features * **api:** add new Response completed_at prop ([f077752](https://github.com/openai/openai-python/commit/f077752f4a8364a74f784f8fb1cbe31277e1762b)) ### Chores * **internal:** codegen related update ([e7daba6](https://github.com/openai/openai-python/commit/e7daba6662a3c30f73d991e96cb19d2b54d772e0)) ## 2.14.0 (2025-12-19) Full Changelog: [v2.13.0...v2.14.0](https://github.com/openai/openai-python/compare/v2.13.0...v2.14.0) ### Features * **api:** slugs for new audio models; make all `model` params accept strings ([e517792](https://github.com/openai/openai-python/commit/e517792b58d1768cfb3432a555a354ae0a9cfa21)) ### Bug Fixes * use async_to_httpx_files in patch method ([a6af9ee](https://github.com/openai/openai-python/commit/a6af9ee5643197222f328d5e73a80ab3515c32e2)) ### Chores * **internal:** add `--fix` argument to lint script ([93107ef](https://github.com/openai/openai-python/commit/93107ef36abcfd9c6b1419533a1720031f03caec)) ## 2.13.0 (2025-12-16) Full Changelog: [v2.12.0...v2.13.0](https://github.com/openai/openai-python/compare/v2.12.0...v2.13.0) ### Features * **api:** gpt-image-1.5 ([1c88f03](https://github.com/openai/openai-python/commit/1c88f03bb48aa67426744e5b74f6197f30f61c73)) ### Chores * **ci:** add CI job to detect breaking changes with the Agents SDK ([#1436](https://github.com/openai/openai-python/issues/1436)) ([237c91e](https://github.com/openai/openai-python/commit/237c91ee6738b6764b139fd7afa68294d3ee0153)) * **internal:** add missing files argument to base client ([e6d6fd5](https://github.com/openai/openai-python/commit/e6d6fd5989d76358ea5d9abb5949aa87646cbef6)) ## 2.12.0 (2025-12-15) Full Changelog: [v2.11.0...v2.12.0](https://github.com/openai/openai-python/compare/v2.11.0...v2.12.0) ### Features * **api:** api update ([a95c4d0](https://github.com/openai/openai-python/commit/a95c4d0952ff5eb767206574e687cb029a49a4ab)) * **api:** fix grader input list, add dated slugs for sora-2 ([b2c389b](https://github.com/openai/openai-python/commit/b2c389bf5c3bde50bac2d9f60cce58f4aef44a41)) ## 2.11.0 (2025-12-11) Full Changelog: [v2.10.0...v2.11.0](https://github.com/openai/openai-python/compare/v2.10.0...v2.11.0) ### Features * **api:** gpt 5.2 ([dd9b8e8](https://github.com/openai/openai-python/commit/dd9b8e85cf91fe0d7470143fba10fe950ec740c4)) ## 2.10.0 (2025-12-10) Full Changelog: [v2.9.0...v2.10.0](https://github.com/openai/openai-python/compare/v2.9.0...v2.10.0) ### Features * **api:** make model required for the responses/compact endpoint ([a12936b](https://github.com/openai/openai-python/commit/a12936b18cf19009d4e6d586c9b1958359636dbe)) ### Bug Fixes * **types:** allow pyright to infer TypedDict types within SequenceNotStr ([8f0d230](https://github.com/openai/openai-python/commit/8f0d23066c1edc38a6e9858b054dceaf92ae001b)) ### Chores * add missing docstrings ([f20a9a1](https://github.com/openai/openai-python/commit/f20a9a18a421ba69622c77ab539509d218e774eb)) * **internal:** update docstring ([9a993f2](https://github.com/openai/openai-python/commit/9a993f2261b6524aa30b955e006c7ea89f086968)) ## 2.9.0 (2025-12-04) Full Changelog: [v2.8.1...v2.9.0](https://github.com/openai/openai-python/compare/v2.8.1...v2.9.0) ### Features * **api:** gpt-5.1-codex-max and responses/compact ([22f646e](https://github.com/openai/openai-python/commit/22f646e985b7c93782cf695edbe643844cae7017)) ### Bug Fixes * **client:** avoid mutating user-provided response config object ([#2700](https://github.com/openai/openai-python/issues/2700)) ([e040d22](https://github.com/openai/openai-python/commit/e040d22c2df068e908f69dc6b892e7f8b3fe6e99)) * ensure streams are always closed ([0b1a27f](https://github.com/openai/openai-python/commit/0b1a27f08639d14dfe40bf80b48e2b8a1a51593c)) * **streaming:** correct indentation ([575bbac](https://github.com/openai/openai-python/commit/575bbac13b3a57731a4e07b67636ae94463d43fa)) ### Chores * **deps:** mypy 1.18.1 has a regression, pin to 1.17 ([22cd586](https://github.com/openai/openai-python/commit/22cd586dbd5484b47f625da55db697691116b22b)) * **docs:** use environment variables for authentication in code snippets ([c2a3cd5](https://github.com/openai/openai-python/commit/c2a3cd502bfb03f68f62f50aed15a40458c0996e)) * **internal:** codegen related update ([307a066](https://github.com/openai/openai-python/commit/307a0664383b9d1d4151bc1a05a78c4fdcdcc9b0)) * update lockfile ([b4109c5](https://github.com/openai/openai-python/commit/b4109c5fcf971ccfb25b4bdaef0bf36999f9eca5)) ## 2.8.1 (2025-11-17) Full Changelog: [v2.8.0...v2.8.1](https://github.com/openai/openai-python/compare/v2.8.0...v2.8.1) ### Bug Fixes * **api:** align types of input items / output items for typescript ([64c9fb3](https://github.com/openai/openai-python/commit/64c9fb3fcc79f0049b3a36bd429faf0600d969f6)) ## 2.8.0 (2025-11-13) Full Changelog: [v2.7.2...v2.8.0](https://github.com/openai/openai-python/compare/v2.7.2...v2.8.0) ### Features * **api:** gpt 5.1 ([8d9f2ca](https://github.com/openai/openai-python/commit/8d9f2cab4cb2e12f6e2ab1de967f858736a656ac)) ### Bug Fixes * **compat:** update signatures of `model_dump` and `model_dump_json` for Pydantic v1 ([c7bd234](https://github.com/openai/openai-python/commit/c7bd234b18239fcdbf0edb1b51ca9116c0ac7251)) ## 2.7.2 (2025-11-10) Full Changelog: [v2.7.1...v2.7.2](https://github.com/openai/openai-python/compare/v2.7.1...v2.7.2) ### Bug Fixes * compat with Python 3.14 ([15a7ec8](https://github.com/openai/openai-python/commit/15a7ec8a753d7f57d525fca60c547fd5331cb214)) ### Chores * **package:** drop Python 3.8 support ([afc14f2](https://github.com/openai/openai-python/commit/afc14f2e42e7a8174f2ff1a5672829b808a716bf)) ## 2.7.1 (2025-11-04) Full Changelog: [v2.7.0...v2.7.1](https://github.com/openai/openai-python/compare/v2.7.0...v2.7.1) ### Bug Fixes * **api:** fix nullability of logprobs ([373b7f6](https://github.com/openai/openai-python/commit/373b7f6e4255dfef3ccd92520011e8ba44e8b7f0)) ## 2.7.0 (2025-11-03) Full Changelog: [v2.6.1...v2.7.0](https://github.com/openai/openai-python/compare/v2.6.1...v2.7.0) ### Features * **api:** Realtime API token_limits, Hybrid searching ranking options ([5b43992](https://github.com/openai/openai-python/commit/5b4399219d7ed326411aec524d25ef2b8e3152fc)) * **api:** remove InputAudio from ResponseInputContent ([bd70a33](https://github.com/openai/openai-python/commit/bd70a33234741fa68c185105e4f53cc0275a2a50)) ### Bug Fixes * **client:** close streams without requiring full consumption ([d8bb7d6](https://github.com/openai/openai-python/commit/d8bb7d6d728c5481de4198eebe668b67803ae14a)) * **readme:** update realtime examples ([#2714](https://github.com/openai/openai-python/issues/2714)) ([d0370a8](https://github.com/openai/openai-python/commit/d0370a8d61fc2f710a34d8aad48f649a9683106d)) * **uploads:** avoid file handle leak ([4f1b691](https://github.com/openai/openai-python/commit/4f1b691ab4db41aebd397ec41942b43fb0f0743c)) ### Chores * **internal/tests:** avoid race condition with implicit client cleanup ([933d23b](https://github.com/openai/openai-python/commit/933d23bd8d7809c77e0796becfe052167d44d40a)) * **internal:** grammar fix (it's -> its) ([f7e9e9e](https://github.com/openai/openai-python/commit/f7e9e9e4f43039f19a41375a6d2b2bdc2264dad7)) ## 2.6.1 (2025-10-24) Full Changelog: [v2.6.0...v2.6.1](https://github.com/openai/openai-python/compare/v2.6.0...v2.6.1) ### Bug Fixes * **api:** docs updates ([d01a0c9](https://github.com/openai/openai-python/commit/d01a0c96ecb94c78b7e16546790c573704b7515b)) ### Chores * **client:** clean up custom translations code ([cfb9e25](https://github.com/openai/openai-python/commit/cfb9e25855b8eb020abe02cdd99566adf474e821)) ## 2.6.0 (2025-10-20) Full Changelog: [v2.5.0...v2.6.0](https://github.com/openai/openai-python/compare/v2.5.0...v2.6.0) ### Features * **api:** Add responses.input_tokens.count ([6dd09e2](https://github.com/openai/openai-python/commit/6dd09e2829f385f72b28620888d91a4493c96772)) ### Bug Fixes * **api:** internal openapi updates ([caabd7c](https://github.com/openai/openai-python/commit/caabd7c81f0f557f66dc0089af460185a5816c11)) ## 2.5.0 (2025-10-17) Full Changelog: [v2.4.0...v2.5.0](https://github.com/openai/openai-python/compare/v2.4.0...v2.5.0) ### Features * **api:** api update ([8b280d5](https://github.com/openai/openai-python/commit/8b280d57d6d361bc3a032e030158f6859c445291)) ### Chores * bump `httpx-aiohttp` version to 0.1.9 ([67f2f0a](https://github.com/openai/openai-python/commit/67f2f0afe51dab9d5899fe18b1a4e86b2c774d10)) ## 2.4.0 (2025-10-16) Full Changelog: [v2.3.0...v2.4.0](https://github.com/openai/openai-python/compare/v2.3.0...v2.4.0) ### Features * **api:** Add support for gpt-4o-transcribe-diarize on audio/transcriptions endpoint ([bdbe9b8](https://github.com/openai/openai-python/commit/bdbe9b8f440209afa2979db4a9eda9579b3d2550)) ### Chores * fix dangling comment ([da14e99](https://github.com/openai/openai-python/commit/da14e9960608f7ade6f5cdf91967830c8a6c1657)) * **internal:** detect missing future annotations with ruff ([2672b8f](https://github.com/openai/openai-python/commit/2672b8f0726300f7c62c356f25545ef0b3c0bb2e)) ## 2.3.0 (2025-10-10) Full Changelog: [v2.2.0...v2.3.0](https://github.com/openai/openai-python/compare/v2.2.0...v2.3.0) ### Features * **api:** comparison filter in/not in ([aa49f62](https://github.com/openai/openai-python/commit/aa49f626a6ea9d77ad008badfb3741e16232d62f)) ### Chores * **package:** bump jiter to >=0.10.0 to support Python 3.14 ([#2618](https://github.com/openai/openai-python/issues/2618)) ([aa445ca](https://github.com/openai/openai-python/commit/aa445cab5c93c6908697fe98e73e16963330b141)) ## 2.2.0 (2025-10-06) Full Changelog: [v2.1.0...v2.2.0](https://github.com/openai/openai-python/compare/v2.1.0...v2.2.0) ### Features * **api:** dev day 2025 launches ([38ac009](https://github.com/openai/openai-python/commit/38ac0093ebb3419b1e2280d0dc2d26c74a2bbbec)) ### Bug Fixes * **client:** add chatkit to beta resource ([de3e561](https://github.com/openai/openai-python/commit/de3e5619d0a85b17906a9416039ef309e820dc0f)) ## 2.1.0 (2025-10-02) Full Changelog: [v2.0.1...v2.1.0](https://github.com/openai/openai-python/compare/v2.0.1...v2.1.0) ### Features * **api:** add support for realtime calls ([7f7925b](https://github.com/openai/openai-python/commit/7f7925b4074ecbf879714698000e10fa0519d51a)) ## 2.0.1 (2025-10-01) Full Changelog: [v2.0.0...v2.0.1](https://github.com/openai/openai-python/compare/v2.0.0...v2.0.1) ### Bug Fixes * **api:** add status, approval_request_id to MCP tool call ([2a02255](https://github.com/openai/openai-python/commit/2a022553f83b636defcfda3b1c6f4b12d901357b)) ## 2.0.0 (2025-09-30) Full Changelog: [v1.109.1...v2.0.0](https://github.com/openai/openai-python/compare/v1.109.1...v2.0.0) ### ⚠ BREAKING CHANGES * **api:** `ResponseFunctionToolCallOutputItem.output` and `ResponseCustomToolCallOutput.output` now return `string | Array` instead of `string` only. This may break existing callsites that assume `output` is always a string. ### Features * **api:** Support images and files for function call outputs in responses, BatchUsage ([4105376](https://github.com/openai/openai-python/commit/4105376a60293581371fd5635b805b717d24aa19)) ## 1.109.1 (2025-09-24) Full Changelog: [v1.109.0...v1.109.1](https://github.com/openai/openai-python/compare/v1.109.0...v1.109.1) ### Bug Fixes * **compat:** compat with `pydantic<2.8.0` when using additional fields ([5d95ecf](https://github.com/openai/openai-python/commit/5d95ecf7abd65f3e4e273be14c80f9b4cd91ffe8)) ## 1.109.0 (2025-09-23) Full Changelog: [v1.108.2...v1.109.0](https://github.com/openai/openai-python/compare/v1.108.2...v1.109.0) ### Features * **api:** gpt-5-codex ([34502b5](https://github.com/openai/openai-python/commit/34502b5a175f8a10ea8694fcea38fe7308de89ef)) ## 1.108.2 (2025-09-22) Full Changelog: [v1.108.1...v1.108.2](https://github.com/openai/openai-python/compare/v1.108.1...v1.108.2) ### Bug Fixes * **api:** fix mcp tool name ([fd1c673](https://github.com/openai/openai-python/commit/fd1c673fa8d5581b38c69c37aa4fd1fd251259a2)) ### Chores * **api:** openapi updates for conversations ([3224f6f](https://github.com/openai/openai-python/commit/3224f6f9b4221b954a8f63de66bcaab389164ee5)) * do not install brew dependencies in ./scripts/bootstrap by default ([6764b00](https://github.com/openai/openai-python/commit/6764b00bcb8aeab41e73d2fcaf6c7a18ea9f7909)) * improve example values ([20b58e1](https://github.com/openai/openai-python/commit/20b58e164f9f28b9fc562968263fa3eacc6f5c7c)) ## 1.108.1 (2025-09-19) Full Changelog: [v1.108.0...v1.108.1](https://github.com/openai/openai-python/compare/v1.108.0...v1.108.1) ### Features * **api:** add reasoning_text ([18d8e12](https://github.com/openai/openai-python/commit/18d8e12061d1fd4e09d24986ff6e38c5063013e9)) ### Chores * **types:** change optional parameter type from NotGiven to Omit ([acc190a](https://github.com/openai/openai-python/commit/acc190a29526e64db6074e7f21aca800423c128c)) ## 1.108.0 (2025-09-17) Full Changelog: [v1.107.3...v1.108.0](https://github.com/openai/openai-python/compare/v1.107.3...v1.108.0) ### Features * **api:** type updates for conversations, reasoning_effort and results for evals ([c2ee28c](https://github.com/openai/openai-python/commit/c2ee28c1b77eed98766fbb01cf1ad2ee240f412e)) ### Chores * **internal:** update pydantic dependency ([369d10a](https://github.com/openai/openai-python/commit/369d10a40dfe744f6bfc10c99eb1f58176500120)) ## 1.107.3 (2025-09-15) Full Changelog: [v1.107.2...v1.107.3](https://github.com/openai/openai-python/compare/v1.107.2...v1.107.3) ### Chores * **api:** docs and spec refactoring ([9bab5da](https://github.com/openai/openai-python/commit/9bab5da1802c3575c58e73ed1470dd5fa61fd1d2)) * **tests:** simplify `get_platform` test ([0b1f6a2](https://github.com/openai/openai-python/commit/0b1f6a28d5a59e10873264e976d2e332903eef29)) ## 1.107.2 (2025-09-12) Full Changelog: [v1.107.1...v1.107.2](https://github.com/openai/openai-python/compare/v1.107.1...v1.107.2) ### Chores * **api:** Minor docs and type updates for realtime ([ab6a10d](https://github.com/openai/openai-python/commit/ab6a10da4ed7e6386695b6f5f29149d4870f85c9)) * **tests:** simplify `get_platform` test ([01f03e0](https://github.com/openai/openai-python/commit/01f03e0ad1f9ab3f2ed8b7c13d652263c6d06378)) ## 1.107.1 (2025-09-10) Full Changelog: [v1.107.0...v1.107.1](https://github.com/openai/openai-python/compare/v1.107.0...v1.107.1) ### Chores * **api:** fix realtime GA types ([570fc5a](https://github.com/openai/openai-python/commit/570fc5a28ada665fd658b24675361680cfeb086f)) ## 1.107.0 (2025-09-08) Full Changelog: [v1.106.1...v1.107.0](https://github.com/openai/openai-python/compare/v1.106.1...v1.107.0) ### Features * **api:** ship the RealtimeGA API shape ([dc319d8](https://github.com/openai/openai-python/commit/dc319d8bbb3a20108399c1d15f98e63bdd84eb5c)) ### Chores * **internal:** codegen related update ([b79b7ca](https://github.com/openai/openai-python/commit/b79b7ca3a72009a036db0a344b500f616ca0443f)) ## 1.106.1 (2025-09-04) Full Changelog: [v1.106.0...v1.106.1](https://github.com/openai/openai-python/compare/v1.106.0...v1.106.1) ### Chores * **internal:** move mypy configurations to `pyproject.toml` file ([ca413a2](https://github.com/openai/openai-python/commit/ca413a277496c3b883b103ad1138a886e89ae15e)) ## 1.106.0 (2025-09-04) Full Changelog: [v1.105.0...v1.106.0](https://github.com/openai/openai-python/compare/v1.105.0...v1.106.0) ### Features * **client:** support callable api_key ([#2588](https://github.com/openai/openai-python/issues/2588)) ([e1bad01](https://github.com/openai/openai-python/commit/e1bad015b8a2b98bfee955a24bc931347a58efc1)) * improve future compat with pydantic v3 ([6645d93](https://github.com/openai/openai-python/commit/6645d9317a240982928b92c2f4af0381db6edc09)) ## 1.105.0 (2025-09-03) Full Changelog: [v1.104.2...v1.105.0](https://github.com/openai/openai-python/compare/v1.104.2...v1.105.0) ### Features * **api:** Add gpt-realtime models ([8502041](https://github.com/openai/openai-python/commit/85020414808314df9cb42e020b11baff12f18f16)) ## 1.104.2 (2025-09-02) Full Changelog: [v1.104.1...v1.104.2](https://github.com/openai/openai-python/compare/v1.104.1...v1.104.2) ### Bug Fixes * **types:** add aliases back for web search tool types ([2521cd8](https://github.com/openai/openai-python/commit/2521cd8445906e418dbae783b0d7c375ad91d49d)) ## 1.104.1 (2025-09-02) Full Changelog: [v1.104.0...v1.104.1](https://github.com/openai/openai-python/compare/v1.104.0...v1.104.1) ### Chores * **api:** manual updates for ResponseInputAudio ([0db5061](https://github.com/openai/openai-python/commit/0db50619663656ba97bba30ab640bbb33683d196)) ## 1.104.0 (2025-09-02) Full Changelog: [v1.103.0...v1.104.0](https://github.com/openai/openai-python/compare/v1.103.0...v1.104.0) ### Features * **types:** replace List[str] with SequenceNotStr in params ([bc00bda](https://github.com/openai/openai-python/commit/bc00bda880a80089be8a1758c016266ca72dab2c)) ### Bug Fixes * **types:** update more types to use SequenceNotStr ([cff135c](https://github.com/openai/openai-python/commit/cff135cb7059ef1bf8f9b101a83529fc0cee37c4)) * **types:** update some types to SequenceNotStr ([03f8b88](https://github.com/openai/openai-python/commit/03f8b88a0d428b74a7822e678a60d0ef106ea961)) ### Chores * remove unused import ([ac7795b](https://github.com/openai/openai-python/commit/ac7795b50d956ec5dc468302e8e3579a0467edcb)) ## 1.103.0 (2025-09-02) Full Changelog: [v1.102.0...v1.103.0](https://github.com/openai/openai-python/compare/v1.102.0...v1.103.0) ### Features * **api:** realtime API updates ([b7c2ddc](https://github.com/openai/openai-python/commit/b7c2ddc5e5dedda01015b3d0e14ea6eb68c282d3)) ### Bug Fixes * **responses:** add missing params to stream() method ([bfc0673](https://github.com/openai/openai-python/commit/bfc06732ffe3764cb95cef9f23b4b5c0d312826a)) ### Chores * bump `inline-snapshot` version to 0.28.0 ([#2590](https://github.com/openai/openai-python/issues/2590)) ([a6b0872](https://github.com/openai/openai-python/commit/a6b087226587d4cc4f59f1f09a595921b2823ef2)) * **client:** format imports ([7ae3020](https://github.com/openai/openai-python/commit/7ae3020b3ca7de21e6e9a0a1c40908e655f6cad5)) * **internal:** add Sequence related utils ([d3d72b9](https://github.com/openai/openai-python/commit/d3d72b9ce3c0885bf2b6934ac57d9e84f8653208)) * **internal:** fix formatting ([3ab273f](https://github.com/openai/openai-python/commit/3ab273f21e601f088be7502b7bb5d249fc386d6a)) * **internal:** minor formatting change ([478a348](https://github.com/openai/openai-python/commit/478a34881c968e9cab9d93ac2cf8da2fcb37c46c)) * **internal:** update pyright exclude list ([66e440f](https://github.com/openai/openai-python/commit/66e440fac3ca388400392c64211450dedc491c11)) ## 1.102.0 (2025-08-26) Full Changelog: [v1.101.0...v1.102.0](https://github.com/openai/openai-python/compare/v1.101.0...v1.102.0) ### Features * **api:** add web search filters ([1c199a8](https://github.com/openai/openai-python/commit/1c199a8dc85f773ae656fe850fdfb80b91f8f6b1)) ### Bug Fixes * avoid newer type syntax ([bd0c668](https://github.com/openai/openai-python/commit/bd0c668d754b89c78c2c9ad2e081258c04aaece6)) ### Chores * **internal:** change ci workflow machines ([3e129d5](https://github.com/openai/openai-python/commit/3e129d5e49f6391dea7497132cb3cfed8e5dd8ee)) * **internal:** codegen related update ([b6dc170](https://github.com/openai/openai-python/commit/b6dc170832d719fc5028cfe234748c22e6e168aa)) ## 1.101.0 (2025-08-21) Full Changelog: [v1.100.3...v1.101.0](https://github.com/openai/openai-python/compare/v1.100.3...v1.101.0) ### Features * **api:** Add connectors support for MCP tool ([a47f962](https://github.com/openai/openai-python/commit/a47f962daf579c142b8af5579be732772b688a29)) * **api:** adding support for /v1/conversations to the API ([e30bcbc](https://github.com/openai/openai-python/commit/e30bcbc0cb7c827af779bee6971f976261abfb67)) ### Chores * update github action ([7333b28](https://github.com/openai/openai-python/commit/7333b282718a5f6977f30e1a2548207b3a089bd4)) ## 1.100.3 (2025-08-20) Full Changelog: [v1.100.2...v1.100.3](https://github.com/openai/openai-python/compare/v1.100.2...v1.100.3) ### Chores * **internal/ci:** setup breaking change detection ([ca2f936](https://github.com/openai/openai-python/commit/ca2f93600238e875f26395faf6afbefaf15b7c97)) ## 1.100.2 (2025-08-19) Full Changelog: [v1.100.1...v1.100.2](https://github.com/openai/openai-python/compare/v1.100.1...v1.100.2) ### Chores * **api:** accurately represent shape for verbosity on Chat Completions ([c39d5fd](https://github.com/openai/openai-python/commit/c39d5fd3f5429c6d41f257669a1dd4c67a477455)) ## 1.100.1 (2025-08-18) Full Changelog: [v1.100.0...v1.100.1](https://github.com/openai/openai-python/compare/v1.100.0...v1.100.1) ### Bug Fixes * **types:** revert response text config deletion ([ac4fb19](https://github.com/openai/openai-python/commit/ac4fb1922ae125c8310c30e402932e8bb2976f58)) ## 1.100.0 (2025-08-18) Full Changelog: [v1.99.9...v1.100.0](https://github.com/openai/openai-python/compare/v1.99.9...v1.100.0) ### Features * **api:** add new text parameters, expiration options ([e3dfa7c](https://github.com/openai/openai-python/commit/e3dfa7c417b8c750ff62d98650e75e72ad9b1477)) ## 1.99.9 (2025-08-12) Full Changelog: [v1.99.8...v1.99.9](https://github.com/openai/openai-python/compare/v1.99.8...v1.99.9) ### Bug Fixes * **types:** actually fix ChatCompletionMessageToolCall type ([20cb0c8](https://github.com/openai/openai-python/commit/20cb0c86d598e196386ff43db992f6497eb756d0)) ## 1.99.8 (2025-08-11) Full Changelog: [v1.99.7...v1.99.8](https://github.com/openai/openai-python/compare/v1.99.7...v1.99.8) ### Bug Fixes * **internal/tests:** correct snapshot update comment ([2784a7a](https://github.com/openai/openai-python/commit/2784a7a7da24ddba74b5717f07d67546864472b9)) * **types:** revert ChatCompletionMessageToolCallUnion breaking change ([ba54e03](https://github.com/openai/openai-python/commit/ba54e03bc2d21825d891685bf3bad4a9253cbeb0)) ### Chores * **internal/tests:** add inline snapshot format command ([8107db8](https://github.com/openai/openai-python/commit/8107db8ff738baa65fe4cf2f2d7f1acd29219c78)) * **internal:** fix formatting ([f03a03d](https://github.com/openai/openai-python/commit/f03a03de8c84740209d021598ff8bf56b6d3c684)) * **tests:** add responses output_text test ([971347b](https://github.com/openai/openai-python/commit/971347b3a05f79c51abd11c86b382ca73c28cefb)) ### Refactors * **tests:** share snapshot utils ([791c567](https://github.com/openai/openai-python/commit/791c567cd87fb8d587965773b1da0404c7848c68)) ## 1.99.7 (2025-08-11) Full Changelog: [v1.99.6...v1.99.7](https://github.com/openai/openai-python/compare/v1.99.6...v1.99.7) ### Bug Fixes * **types:** rename ChatCompletionMessageToolCallParam ([48085e2](https://github.com/openai/openai-python/commit/48085e2f473799d079e71d48d2f5612a6fbeb976)) * **types:** revert ChatCompletionMessageToolCallParam to a TypedDict ([c8e9cec](https://github.com/openai/openai-python/commit/c8e9cec5c93cc022fff546f27161717f769d1f81)) ## 1.99.6 (2025-08-09) Full Changelog: [v1.99.5...v1.99.6](https://github.com/openai/openai-python/compare/v1.99.5...v1.99.6) ### Bug Fixes * **types:** re-export more tool call types ([8fe5741](https://github.com/openai/openai-python/commit/8fe574131cfe8f0453788cc6105d22834e7c102f)) ### Chores * **internal:** update comment in script ([e407bb5](https://github.com/openai/openai-python/commit/e407bb52112ad73e5eedf929434ee4ff7ac5a5a8)) * update @stainless-api/prism-cli to v5.15.0 ([a1883fc](https://github.com/openai/openai-python/commit/a1883fcdfa02b81e5129bdb43206597a51f885fa)) ## 1.99.5 (2025-08-08) Full Changelog: [v1.99.4...v1.99.5](https://github.com/openai/openai-python/compare/v1.99.4...v1.99.5) ### Bug Fixes * **client:** fix verbosity parameter location in Responses ([2764ff4](https://github.com/openai/openai-python/commit/2764ff459eb8b309d25b39b40e363b16a5b95019)) ## 1.99.4 (2025-08-08) Full Changelog: [v1.99.3...v1.99.4](https://github.com/openai/openai-python/compare/v1.99.3...v1.99.4) ### Bug Fixes * **types:** rename chat completion tool ([8d3bf88](https://github.com/openai/openai-python/commit/8d3bf88f5bc11cf30b8b050c24b2cc5a3807614f)) * **types:** revert ChatCompletionToolParam to a TypedDict ([3f4ae72](https://github.com/openai/openai-python/commit/3f4ae725af53e631ddc128c1c6862ecf0b08e073)) ## 1.99.3 (2025-08-07) Full Changelog: [v1.99.2...v1.99.3](https://github.com/openai/openai-python/compare/v1.99.2...v1.99.3) ### Bug Fixes * **responses:** add output_text back ([585a4f1](https://github.com/openai/openai-python/commit/585a4f15e5a088bf8afee745bc4a7803775ac283)) ## 1.99.2 (2025-08-07) Full Changelog: [v1.99.1...v1.99.2](https://github.com/openai/openai-python/compare/v1.99.1...v1.99.2) ### Features * **api:** adds GPT-5 and new API features: platform.openai.com/docs/guides/gpt-5 ([ed370d8](https://github.com/openai/openai-python/commit/ed370d805e4d5d1ec14a136f5b2516751277059f)) ### Bug Fixes * **types:** correct tool types ([0c57bd7](https://github.com/openai/openai-python/commit/0c57bd7f2183a20b714d04edea380a4df0464a40)) ### Chores * **tests:** bump inline-snapshot dependency ([e236fde](https://github.com/openai/openai-python/commit/e236fde99a335fcaac9760f324e4807ce2cf7cba)) ## 1.99.1 (2025-08-05) Full Changelog: [v1.99.0...v1.99.1](https://github.com/openai/openai-python/compare/v1.99.0...v1.99.1) ### Bug Fixes * **internal:** correct event imports ([2a6d143](https://github.com/openai/openai-python/commit/2a6d1436288a07f67f6afefe5c0b5d6ae32d7e70)) ## 1.99.0 (2025-08-05) Full Changelog: [v1.98.0...v1.99.0](https://github.com/openai/openai-python/compare/v1.98.0...v1.99.0) ### Features * **api:** manual updates ([d4aa726](https://github.com/openai/openai-python/commit/d4aa72602bf489ef270154b881b3967d497d4220)) * **client:** support file upload requests ([0772e6e](https://github.com/openai/openai-python/commit/0772e6ed8310e15539610b003dd73f72f474ec0c)) ### Bug Fixes * add missing prompt_cache_key & prompt_cache_key params ([00b49ae](https://github.com/openai/openai-python/commit/00b49ae8d44ea396ac0536fc3ce4658fc669e2f5)) ### Chores * **internal:** fix ruff target version ([aa6b252](https://github.com/openai/openai-python/commit/aa6b252ae0f25f195dede15755e05dd2f542f42d)) ## 1.98.0 (2025-07-30) Full Changelog: [v1.97.2...v1.98.0](https://github.com/openai/openai-python/compare/v1.97.2...v1.98.0) ### Features * **api:** manual updates ([88a8036](https://github.com/openai/openai-python/commit/88a8036c5ea186f36c57029ef4501a0833596f56)) ## 1.97.2 (2025-07-30) Full Changelog: [v1.97.1...v1.97.2](https://github.com/openai/openai-python/compare/v1.97.1...v1.97.2) ### Chores * **client:** refactor streaming slightly to better future proof it ([71c0c74](https://github.com/openai/openai-python/commit/71c0c747132221b798e419bc5a37baf67173d34e)) * **project:** add settings file for vscode ([29c22c9](https://github.com/openai/openai-python/commit/29c22c90fd229983355089f95d0bba9de15efedb)) ## 1.97.1 (2025-07-22) Full Changelog: [v1.97.0...v1.97.1](https://github.com/openai/openai-python/compare/v1.97.0...v1.97.1) ### Bug Fixes * **parsing:** ignore empty metadata ([58c359f](https://github.com/openai/openai-python/commit/58c359ff67fd6103268e4405600fd58844b6f27b)) * **parsing:** parse extra field types ([d524b7e](https://github.com/openai/openai-python/commit/d524b7e201418ccc9b5c2206da06d1be011808e5)) ### Chores * **api:** event shapes more accurate ([f3a9a92](https://github.com/openai/openai-python/commit/f3a9a9229280ecb7e0b2779dd44290df6d9824ef)) ## 1.97.0 (2025-07-16) Full Changelog: [v1.96.1...v1.97.0](https://github.com/openai/openai-python/compare/v1.96.1...v1.97.0) ### Features * **api:** manual updates ([ed8e899](https://github.com/openai/openai-python/commit/ed8e89953d11bd5f44fa531422bdbb7a577ab426)) ## 1.96.1 (2025-07-15) Full Changelog: [v1.96.0...v1.96.1](https://github.com/openai/openai-python/compare/v1.96.0...v1.96.1) ### Chores * **api:** update realtime specs ([b68b71b](https://github.com/openai/openai-python/commit/b68b71b178719e0b49ecfe34486b9d9ac0627924)) ## 1.96.0 (2025-07-15) Full Changelog: [v1.95.1...v1.96.0](https://github.com/openai/openai-python/compare/v1.95.1...v1.96.0) ### Features * clean up environment call outs ([87c2e97](https://github.com/openai/openai-python/commit/87c2e979e0ec37347b7f595c2696408acd25fe20)) ### Chores * **api:** update realtime specs, build config ([bf06d88](https://github.com/openai/openai-python/commit/bf06d88b33f9af82a51d9a8af5b7a38925906f7a)) ## 1.95.1 (2025-07-11) Full Changelog: [v1.95.0...v1.95.1](https://github.com/openai/openai-python/compare/v1.95.0...v1.95.1) ### Bug Fixes * **client:** don't send Content-Type header on GET requests ([182b763](https://github.com/openai/openai-python/commit/182b763065fbaaf68491a7e4a15fcb23cac361de)) ## 1.95.0 (2025-07-10) Full Changelog: [v1.94.0...v1.95.0](https://github.com/openai/openai-python/compare/v1.94.0...v1.95.0) ### Features * **api:** add file_url, fix event ID ([265e216](https://github.com/openai/openai-python/commit/265e216396196d66cdfb5f92c5ef1a2a6ff27b5b)) ### Chores * **readme:** fix version rendering on pypi ([1eee5ca](https://github.com/openai/openai-python/commit/1eee5cabf2fd93877cd3ba85d0c6ed2ffd5f159f)) ## 1.94.0 (2025-07-10) Full Changelog: [v1.93.3...v1.94.0](https://github.com/openai/openai-python/compare/v1.93.3...v1.94.0) ### Features * **api:** return better error message on missing embedding ([#2369](https://github.com/openai/openai-python/issues/2369)) ([e53464a](https://github.com/openai/openai-python/commit/e53464ae95f6a041f3267762834e6156c5ce1b57)) ## 1.93.3 (2025-07-09) Full Changelog: [v1.93.2...v1.93.3](https://github.com/openai/openai-python/compare/v1.93.2...v1.93.3) ### Bug Fixes * **parsing:** correctly handle nested discriminated unions ([fc8a677](https://github.com/openai/openai-python/commit/fc8a67715d8f1b45d8639b8b6f9f6590fe358734)) ## 1.93.2 (2025-07-08) Full Changelog: [v1.93.1...v1.93.2](https://github.com/openai/openai-python/compare/v1.93.1...v1.93.2) ### Chores * **internal:** bump pinned h11 dep ([4fca6ae](https://github.com/openai/openai-python/commit/4fca6ae2d0d7f27cbac8d06c3917932767c8c6b8)) * **package:** mark python 3.13 as supported ([2229047](https://github.com/openai/openai-python/commit/2229047b8a549df16c617bddfe3b4521cfd257a5)) ## 1.93.1 (2025-07-07) Full Changelog: [v1.93.0...v1.93.1](https://github.com/openai/openai-python/compare/v1.93.0...v1.93.1) ### Bug Fixes * **ci:** correct conditional ([de6a9ce](https://github.com/openai/openai-python/commit/de6a9ce078731d60b0bdc42a9322548c575f11a3)) * **responses:** add missing arguments to parse ([05590ec](https://github.com/openai/openai-python/commit/05590ec2a96399afd05baf5a3ee1d9a744f09c40)) * **vector stores:** add missing arguments to files.create_and_poll ([3152134](https://github.com/openai/openai-python/commit/3152134510532ec7c522d6b50a820deea205b602)) * **vector stores:** add missing arguments to files.upload_and_poll ([9d4f425](https://github.com/openai/openai-python/commit/9d4f42569d5b59311453b1b11ee1dd2e8a271268)) ### Chores * **ci:** change upload type ([cd4aa88](https://github.com/openai/openai-python/commit/cd4aa889c50581d861728c9606327992485f0d0d)) * **ci:** only run for pushes and fork pull requests ([f89c7eb](https://github.com/openai/openai-python/commit/f89c7eb46c6f081254715d75543cbee3ffa83822)) * **internal:** codegen related update ([bddb8d2](https://github.com/openai/openai-python/commit/bddb8d2091455920e8526068d64f3f8a5cac7ae6)) * **tests:** ensure parse method is in sync with create ([4f58e18](https://github.com/openai/openai-python/commit/4f58e187c12dc8b2c33e9cca284b0429e5cc4de5)) * **tests:** ensure vector store files create and poll method is in sync ([0fe75a2](https://github.com/openai/openai-python/commit/0fe75a28f6109b2d25b015dc99472a06693e0e9f)) ## 1.93.0 (2025-06-27) Full Changelog: [v1.92.3...v1.93.0](https://github.com/openai/openai-python/compare/v1.92.3...v1.93.0) ### Features * **cli:** add support for fine_tuning.jobs ([#1224](https://github.com/openai/openai-python/issues/1224)) ([e362bfd](https://github.com/openai/openai-python/commit/e362bfd10dfd04176560b964470ab0c517c601f3)) ## 1.92.3 (2025-06-27) Full Changelog: [v1.92.2...v1.92.3](https://github.com/openai/openai-python/compare/v1.92.2...v1.92.3) ### Bug Fixes * **client:** avoid encoding error with empty API keys ([5a3e64e](https://github.com/openai/openai-python/commit/5a3e64e0cc761dbaa613fb22ec16e7e73c3bcf72)) ### Documentation * **examples/realtime:** mention macOS requirements ([#2142](https://github.com/openai/openai-python/issues/2142)) ([27bf6b2](https://github.com/openai/openai-python/commit/27bf6b2a933c61d5ec23fd266148af888f69f5c1)) ## 1.92.2 (2025-06-26) Full Changelog: [v1.92.1...v1.92.2](https://github.com/openai/openai-python/compare/v1.92.1...v1.92.2) ### Chores * **api:** remove unsupported property ([ec24408](https://github.com/openai/openai-python/commit/ec2440864e03278144d7f58b97c31d87903e0843)) ## 1.92.1 (2025-06-26) Full Changelog: [v1.92.0...v1.92.1](https://github.com/openai/openai-python/compare/v1.92.0...v1.92.1) ### Chores * **client:** sync stream/parse methods over ([e2536cf](https://github.com/openai/openai-python/commit/e2536cfd74224047cece9c2ad86f0ffe51c0667c)) * **docs:** update README to include links to docs on Webhooks ([ddbf9f1](https://github.com/openai/openai-python/commit/ddbf9f1dc47a32257716189f2056b45933328c9c)) ## 1.92.0 (2025-06-26) Full Changelog: [v1.91.0...v1.92.0](https://github.com/openai/openai-python/compare/v1.91.0...v1.92.0) ### Features * **api:** webhook and deep research support ([d3bb116](https://github.com/openai/openai-python/commit/d3bb116f34f470502f902b88131deec43a953b12)) * **client:** move stream and parse out of beta ([0e358ed](https://github.com/openai/openai-python/commit/0e358ed66b317038705fb38958a449d284f3cb88)) ### Bug Fixes * **ci:** release-doctor — report correct token name ([ff8c556](https://github.com/openai/openai-python/commit/ff8c5561e44e8a0902732b5934c97299d2c98d4e)) ### Chores * **internal:** add tests for breaking change detection ([710fe8f](https://github.com/openai/openai-python/commit/710fe8fd5f9e33730338341680152d3f2556dfa0)) * **tests:** skip some failing tests on the latest python versions ([93ccc38](https://github.com/openai/openai-python/commit/93ccc38a8ef1575d77d33d031666d07d10e4af72)) ## 1.91.0 (2025-06-23) Full Changelog: [v1.90.0...v1.91.0](https://github.com/openai/openai-python/compare/v1.90.0...v1.91.0) ### Features * **api:** update api shapes for usage and code interpreter ([060d566](https://github.com/openai/openai-python/commit/060d5661e4a1fcdb953c52facd3e668ee80f9295)) ## 1.90.0 (2025-06-20) Full Changelog: [v1.89.0...v1.90.0](https://github.com/openai/openai-python/compare/v1.89.0...v1.90.0) ### Features * **api:** make model and inputs not required to create response ([11bd62e](https://github.com/openai/openai-python/commit/11bd62eb7e46eec748edaf2e0cecf253ffc1202c)) ## 1.89.0 (2025-06-20) Full Changelog: [v1.88.0...v1.89.0](https://github.com/openai/openai-python/compare/v1.88.0...v1.89.0) ### Features * **client:** add support for aiohttp ([9218b07](https://github.com/openai/openai-python/commit/9218b07727bf6f6eb00953df66de6ab061fecddb)) ### Bug Fixes * **tests:** fix: tests which call HTTP endpoints directly with the example parameters ([35bcc4b](https://github.com/openai/openai-python/commit/35bcc4b80bdbaa31108650f2a515902e83794e5a)) ### Chores * **readme:** update badges ([68044ee](https://github.com/openai/openai-python/commit/68044ee85d1bf324b17d3f60c914df4725d47fc8)) ## 1.88.0 (2025-06-17) Full Changelog: [v1.87.0...v1.88.0](https://github.com/openai/openai-python/compare/v1.87.0...v1.88.0) ### Features * **api:** manual updates ([5d18a84](https://github.com/openai/openai-python/commit/5d18a8448ecbe31597e98ec7f64d7050c831901e)) ### Chores * **ci:** enable for pull requests ([542b0ce](https://github.com/openai/openai-python/commit/542b0ce98f14ccff4f9e1bcbd3a9ea5e4f846638)) * **internal:** minor formatting ([29d723d](https://github.com/openai/openai-python/commit/29d723d1f1baf2a5843293c8647dc7baa16d56d1)) ## 1.87.0 (2025-06-16) Full Changelog: [v1.86.0...v1.87.0](https://github.com/openai/openai-python/compare/v1.86.0...v1.87.0) ### Features * **api:** add reusable prompt IDs ([36bfe6e](https://github.com/openai/openai-python/commit/36bfe6e8ae12a31624ba1a360d9260f0aeec448a)) ### Bug Fixes * **client:** update service_tier on `client.beta.chat.completions` ([aa488d5](https://github.com/openai/openai-python/commit/aa488d5cf210d8640f87216538d4ff79d7181f2a)) ### Chores * **internal:** codegen related update ([b1a31e5](https://github.com/openai/openai-python/commit/b1a31e5ef4387d9f82cf33f9461371651788d381)) * **internal:** update conftest.py ([bba0213](https://github.com/openai/openai-python/commit/bba0213842a4c161f2235e526d50901a336eecef)) * **tests:** add tests for httpx client instantiation & proxies ([bc93712](https://github.com/openai/openai-python/commit/bc9371204f457aee9ed9b6ec1b61c2084f32faf1)) ## 1.86.0 (2025-06-10) Full Changelog: [v1.85.0...v1.86.0](https://github.com/openai/openai-python/compare/v1.85.0...v1.86.0) ### Features * **api:** Add o3-pro model IDs ([d8dd80b](https://github.com/openai/openai-python/commit/d8dd80b1b4e6c73687d7acb6c3f62f0bf4b8282c)) ## 1.85.0 (2025-06-09) Full Changelog: [v1.84.0...v1.85.0](https://github.com/openai/openai-python/compare/v1.84.0...v1.85.0) ### Features * **api:** Add tools and structured outputs to evals ([002cc7b](https://github.com/openai/openai-python/commit/002cc7bb3c315d95b81c2e497f55d21be7fd26f8)) ### Bug Fixes * **responses:** support raw responses for `parse()` ([d459943](https://github.com/openai/openai-python/commit/d459943cc1c81cf9ce5c426edd3ef9112fdf6723)) ## 1.84.0 (2025-06-03) Full Changelog: [v1.83.0...v1.84.0](https://github.com/openai/openai-python/compare/v1.83.0...v1.84.0) ### Features * **api:** add new realtime and audio models, realtime session options ([0acd0da](https://github.com/openai/openai-python/commit/0acd0da6bc0468c6c857711bc5e77d0bc6d31be6)) ### Chores * **api:** update type names ([1924559](https://github.com/openai/openai-python/commit/192455913b38bf0323ddd0e2b1499b114e2111a1)) ## 1.83.0 (2025-06-02) Full Changelog: [v1.82.1...v1.83.0](https://github.com/openai/openai-python/compare/v1.82.1...v1.83.0) ### Features * **api:** Config update for pakrym-stream-param ([88bcf3a](https://github.com/openai/openai-python/commit/88bcf3af9ce8ffa8347547d4d30aacac1ceba939)) * **client:** add follow_redirects request option ([26d715f](https://github.com/openai/openai-python/commit/26d715f4e9b0f2b19e2ac16acc796a949338e1e1)) ### Bug Fixes * **api:** Fix evals and code interpreter interfaces ([2650159](https://github.com/openai/openai-python/commit/2650159f6d01f6eb481cf8c7942142e4fd21ce44)) * **client:** return binary content from `get /containers/{container_id}/files/{file_id}/content` ([f7c80c4](https://github.com/openai/openai-python/commit/f7c80c4368434bd0be7436375076ba33a62f63b5)) ### Chores * **api:** mark some methods as deprecated ([3e2ca57](https://github.com/openai/openai-python/commit/3e2ca571cb6cdd9e15596590605b2f98a4c5a42e)) * deprecate Assistants API ([9d166d7](https://github.com/openai/openai-python/commit/9d166d795e03dea49af680ec9597e9497522187c)) * **docs:** remove reference to rye shell ([c7978e9](https://github.com/openai/openai-python/commit/c7978e9f1640c311022988fcd716cbb5c865daa8)) ## 1.82.1 (2025-05-29) Full Changelog: [v1.82.0...v1.82.1](https://github.com/openai/openai-python/compare/v1.82.0...v1.82.1) ### Bug Fixes * **responses:** don't include `parsed_arguments` when re-serialising ([6d04193](https://github.com/openai/openai-python/commit/6d041937963ce452affcfb3553146ee51acfeb7a)) ### Chores * **internal:** fix release workflows ([361a909](https://github.com/openai/openai-python/commit/361a909a0cc83e5029ea425fd72202ffa8d1a46a)) ## 1.82.0 (2025-05-22) Full Changelog: [v1.81.0...v1.82.0](https://github.com/openai/openai-python/compare/v1.81.0...v1.82.0) ### Features * **api:** new streaming helpers for background responses ([2a65d4d](https://github.com/openai/openai-python/commit/2a65d4de0aaba7801edd0df10f225530fd4969bd)) ### Bug Fixes * **azure:** mark images/edits as a deployment endpoint [#2371](https://github.com/openai/openai-python/issues/2371) ([5d1d5b4](https://github.com/openai/openai-python/commit/5d1d5b4b6072afe9fd7909b1a36014c8c11c1ad6)) ### Documentation * **readme:** another async example fix ([9ec8289](https://github.com/openai/openai-python/commit/9ec8289041f395805c67efd97847480f84eb9dac)) * **readme:** fix async example ([37d0b25](https://github.com/openai/openai-python/commit/37d0b25b6e82cd381e5d1aa6e28f1a1311d02353)) ## 1.81.0 (2025-05-21) Full Changelog: [v1.80.0...v1.81.0](https://github.com/openai/openai-python/compare/v1.80.0...v1.81.0) ### Features * **api:** add container endpoint ([054a210](https://github.com/openai/openai-python/commit/054a210289d7e0db22d2d2a61bbe4d4d9cc0cb47)) ## 1.80.0 (2025-05-21) Full Changelog: [v1.79.0...v1.80.0](https://github.com/openai/openai-python/compare/v1.79.0...v1.80.0) ### Features * **api:** new API tools ([d36ae52](https://github.com/openai/openai-python/commit/d36ae528d55fe87067c4b8c6b2c947cbad5e5002)) ### Chores * **docs:** grammar improvements ([e746145](https://github.com/openai/openai-python/commit/e746145a12b5335d8841aff95c91bbbde8bae8e3)) ## 1.79.0 (2025-05-16) Full Changelog: [v1.78.1...v1.79.0](https://github.com/openai/openai-python/compare/v1.78.1...v1.79.0) ### Features * **api:** further updates for evals API ([32c99a6](https://github.com/openai/openai-python/commit/32c99a6f5885d4bf3511a7f06b70000edd274301)) * **api:** manual updates ([25245e5](https://github.com/openai/openai-python/commit/25245e5e3d0713abfb65b760aee1f12bc61deb41)) * **api:** responses x eval api ([fd586cb](https://github.com/openai/openai-python/commit/fd586cbdf889c9a5c6b9be177ff02fbfffa3eba5)) * **api:** Updating Assistants and Evals API schemas ([98ba7d3](https://github.com/openai/openai-python/commit/98ba7d355551213a13803f68d5642eecbb4ffd39)) ### Bug Fixes * fix create audio transcription endpoint ([e9a89ab](https://github.com/openai/openai-python/commit/e9a89ab7b6387610e433550207a23973b7edda3a)) ### Chores * **ci:** fix installation instructions ([f26c5fc](https://github.com/openai/openai-python/commit/f26c5fc85d98d700b68cb55c8be5d15983a9aeaf)) * **ci:** upload sdks to package manager ([861f105](https://github.com/openai/openai-python/commit/861f1055768168ab04987a42efcd32a07bc93542)) ## 1.78.1 (2025-05-12) Full Changelog: [v1.78.0...v1.78.1](https://github.com/openai/openai-python/compare/v1.78.0...v1.78.1) ### Bug Fixes * **internal:** fix linting due to broken __test__ annotation ([5a7d7a0](https://github.com/openai/openai-python/commit/5a7d7a081138c6473bff44e60d439812ecb85cdf)) * **package:** support direct resource imports ([2293fc0](https://github.com/openai/openai-python/commit/2293fc0dd23a9c756067cdc22b39c18448f35feb)) ## 1.78.0 (2025-05-08) Full Changelog: [v1.77.0...v1.78.0](https://github.com/openai/openai-python/compare/v1.77.0...v1.78.0) ### Features * **api:** Add reinforcement fine-tuning api support ([bebe361](https://github.com/openai/openai-python/commit/bebe36104bd3062d09ab9bbfb4bacfc99e737cb2)) ### Bug Fixes * ignore errors in isinstance() calls on LazyProxy subclasses ([#2343](https://github.com/openai/openai-python/issues/2343)) ([52cbbdf](https://github.com/openai/openai-python/commit/52cbbdf2207567741f16d18f1ea1b0d13d667375)), closes [#2056](https://github.com/openai/openai-python/issues/2056) ### Chores * **internal:** update proxy tests ([b8e848d](https://github.com/openai/openai-python/commit/b8e848d5fb58472cbfa27fb3ed01efc25a05d944)) * use lazy imports for module level client ([4d0f409](https://github.com/openai/openai-python/commit/4d0f409e79a18cce9855fe076f5a50e52b8bafd8)) * use lazy imports for resources ([834813c](https://github.com/openai/openai-python/commit/834813c5cb1a84effc34e5eabed760393e1de806)) ## 1.77.0 (2025-05-02) Full Changelog: [v1.76.2...v1.77.0](https://github.com/openai/openai-python/compare/v1.76.2...v1.77.0) ### Features * **api:** add image sizes, reasoning encryption ([473469a](https://github.com/openai/openai-python/commit/473469afa1a5f0a03f727bdcdadb9fd57872f9c5)) ### Bug Fixes * **parsing:** handle whitespace only strings ([#2007](https://github.com/openai/openai-python/issues/2007)) ([246bc5b](https://github.com/openai/openai-python/commit/246bc5b7559887840717667a0dad465caef66c3b)) ### Chores * only strip leading whitespace ([8467d66](https://github.com/openai/openai-python/commit/8467d666e0ddf1a9f81b8769a5c8a2fef1de20c1)) ## 1.76.2 (2025-04-29) Full Changelog: [v1.76.1...v1.76.2](https://github.com/openai/openai-python/compare/v1.76.1...v1.76.2) ### Chores * **api:** API spec cleanup ([0a4d3e2](https://github.com/openai/openai-python/commit/0a4d3e2b495d22dd42ce1773b870554c64f9b3b2)) ## 1.76.1 (2025-04-29) Full Changelog: [v1.76.0...v1.76.1](https://github.com/openai/openai-python/compare/v1.76.0...v1.76.1) ### Chores * broadly detect json family of content-type headers ([b4b1b08](https://github.com/openai/openai-python/commit/b4b1b086b512eecc0ada7fc1efa45eb506982f13)) * **ci:** only use depot for staging repos ([35312d8](https://github.com/openai/openai-python/commit/35312d80e6bbc1a61d06ad253af9a713b5ef040c)) * **ci:** run on more branches and use depot runners ([a6a45d4](https://github.com/openai/openai-python/commit/a6a45d4af8a4d904b37573a9b223d56106b4887d)) ## 1.76.0 (2025-04-23) Full Changelog: [v1.75.0...v1.76.0](https://github.com/openai/openai-python/compare/v1.75.0...v1.76.0) ### Features * **api:** adding new image model support ([74d7692](https://github.com/openai/openai-python/commit/74d7692e94c9dca96db8793809d75631c22dbb87)) ### Bug Fixes * **pydantic v1:** more robust `ModelField.annotation` check ([#2163](https://github.com/openai/openai-python/issues/2163)) ([7351b12](https://github.com/openai/openai-python/commit/7351b12bc981f56632b92342d9ef26f6fb28d540)) * **pydantic v1:** more robust ModelField.annotation check ([eba7856](https://github.com/openai/openai-python/commit/eba7856db55afb8cb44376a0248587549f7bc65f)) ### Chores * **ci:** add timeout thresholds for CI jobs ([0997211](https://github.com/openai/openai-python/commit/09972119df5dd4c7c8db137c721364787e22d4c6)) * **internal:** fix list file params ([da2113c](https://github.com/openai/openai-python/commit/da2113c60b50b4438459325fcd38d55df3f63d8e)) * **internal:** import reformatting ([b425fb9](https://github.com/openai/openai-python/commit/b425fb906f62550c3669b09b9d8575f3d4d8496b)) * **internal:** minor formatting changes ([aed1d76](https://github.com/openai/openai-python/commit/aed1d767898324cf90328db329e04e89a77579c3)) * **internal:** refactor retries to not use recursion ([8cb8cfa](https://github.com/openai/openai-python/commit/8cb8cfab48a4fed70a756ce50036e7e56e1f9f87)) * **internal:** update models test ([870ad4e](https://github.com/openai/openai-python/commit/870ad4ed3a284d75f44b825503750129284c7906)) * update completion parse signature ([a44016c](https://github.com/openai/openai-python/commit/a44016c64cdefe404e97592808ed3c25411ab27b)) ## 1.75.0 (2025-04-16) Full Changelog: [v1.74.1...v1.75.0](https://github.com/openai/openai-python/compare/v1.74.1...v1.75.0) ### Features * **api:** add o3 and o4-mini model IDs ([4bacbd5](https://github.com/openai/openai-python/commit/4bacbd5503137e266c127dc643ebae496cb4f158)) ## 1.74.1 (2025-04-16) Full Changelog: [v1.74.0...v1.74.1](https://github.com/openai/openai-python/compare/v1.74.0...v1.74.1) ### Chores * **internal:** base client updates ([06303b5](https://github.com/openai/openai-python/commit/06303b501f8c17040c495971a4ee79ae340f6f4a)) * **internal:** bump pyright version ([9fd1c77](https://github.com/openai/openai-python/commit/9fd1c778c3231616bf1331cb1daa86fdfca4cb7f)) ## 1.74.0 (2025-04-14) Full Changelog: [v1.73.0...v1.74.0](https://github.com/openai/openai-python/compare/v1.73.0...v1.74.0) ### Features * **api:** adding gpt-4.1 family of model IDs ([d4dae55](https://github.com/openai/openai-python/commit/d4dae5553ff3a2879b9ab79a6423661b212421f9)) ### Bug Fixes * **chat:** skip azure async filter events ([#2255](https://github.com/openai/openai-python/issues/2255)) ([fd3a38b](https://github.com/openai/openai-python/commit/fd3a38b1ed30af0a9f3302c1cfc6be6b352e65de)) ### Chores * **client:** minor internal fixes ([6071ae5](https://github.com/openai/openai-python/commit/6071ae5e8b4faa465afc8d07370737e66901900a)) * **internal:** update pyright settings ([c8f8beb](https://github.com/openai/openai-python/commit/c8f8bebf852380a224701bc36826291d6387c53d)) ## 1.73.0 (2025-04-12) Full Changelog: [v1.72.0...v1.73.0](https://github.com/openai/openai-python/compare/v1.72.0...v1.73.0) ### Features * **api:** manual updates ([a3253dd](https://github.com/openai/openai-python/commit/a3253dd798c1eccd9810d4fc593e8c2a568bcf4f)) ### Bug Fixes * **perf:** optimize some hot paths ([f79d39f](https://github.com/openai/openai-python/commit/f79d39fbcaea8f366a9e48c06fb1696bab3e607d)) * **perf:** skip traversing types for NotGiven values ([28d220d](https://github.com/openai/openai-python/commit/28d220de3b4a09d80450d0bcc9b347bbf68f81ec)) ### Chores * **internal:** expand CI branch coverage ([#2295](https://github.com/openai/openai-python/issues/2295)) ([0ae783b](https://github.com/openai/openai-python/commit/0ae783b99122975be521365de0b6d2bce46056c9)) * **internal:** reduce CI branch coverage ([2fb7d42](https://github.com/openai/openai-python/commit/2fb7d425cda679a54aa3262090479fd747363bb4)) * slight wording improvement in README ([#2291](https://github.com/openai/openai-python/issues/2291)) ([e020759](https://github.com/openai/openai-python/commit/e0207598d16a2a9cb3cb3a8e8e97fa9cfdccd5e8)) * workaround build errors ([4e10c96](https://github.com/openai/openai-python/commit/4e10c96a483db28dedc2d8c2908765fb7317e049)) ## 1.72.0 (2025-04-08) Full Changelog: [v1.71.0...v1.72.0](https://github.com/openai/openai-python/compare/v1.71.0...v1.72.0) ### Features * **api:** Add evalapi to sdk ([#2287](https://github.com/openai/openai-python/issues/2287)) ([35262fc](https://github.com/openai/openai-python/commit/35262fcef6ccb7d1f75c9abdfdc68c3dcf87ef53)) ### Chores * **internal:** fix examples ([#2288](https://github.com/openai/openai-python/issues/2288)) ([39defd6](https://github.com/openai/openai-python/commit/39defd61e81ea0ec6b898be12e9fb7e621c0e532)) * **internal:** skip broken test ([#2289](https://github.com/openai/openai-python/issues/2289)) ([e2c9bce](https://github.com/openai/openai-python/commit/e2c9bce1f59686ee053b495d06ea118b4a89e09e)) * **internal:** slight transform perf improvement ([#2284](https://github.com/openai/openai-python/issues/2284)) ([746174f](https://github.com/openai/openai-python/commit/746174fae7a018ece5dab54fb0b5a15fcdd18f2f)) * **tests:** improve enum examples ([#2286](https://github.com/openai/openai-python/issues/2286)) ([c9dd81c](https://github.com/openai/openai-python/commit/c9dd81ce0277e8b1f5db5e0a39c4c2bcd9004bcc)) ## 1.71.0 (2025-04-07) Full Changelog: [v1.70.0...v1.71.0](https://github.com/openai/openai-python/compare/v1.70.0...v1.71.0) ### Features * **api:** manual updates ([bf8b4b6](https://github.com/openai/openai-python/commit/bf8b4b69906bfaea622c9c644270e985d92e2df2)) * **api:** manual updates ([3e37aa3](https://github.com/openai/openai-python/commit/3e37aa3e151d9738625a1daf75d6243d6fdbe8f2)) * **api:** manual updates ([dba9b65](https://github.com/openai/openai-python/commit/dba9b656fa5955b6eba8f6910da836a34de8d59d)) * **api:** manual updates ([f0c463b](https://github.com/openai/openai-python/commit/f0c463b47836666d091b5f616871f1b94646d346)) ### Chores * **deps:** allow websockets v15 ([#2281](https://github.com/openai/openai-python/issues/2281)) ([19c619e](https://github.com/openai/openai-python/commit/19c619ea95839129a86c19d5b60133e1ed9f2746)) * **internal:** only run examples workflow in main repo ([#2282](https://github.com/openai/openai-python/issues/2282)) ([c3e0927](https://github.com/openai/openai-python/commit/c3e0927d3fbbb9f753ba12adfa682a4235ba530a)) * **internal:** remove trailing character ([#2277](https://github.com/openai/openai-python/issues/2277)) ([5a21a2d](https://github.com/openai/openai-python/commit/5a21a2d7994e39bb0c86271eeb807983a9ae874a)) * Remove deprecated/unused remote spec feature ([23f76eb](https://github.com/openai/openai-python/commit/23f76eb0b9ddf12bcb04a6ad3f3ec5e956d2863f)) ## 1.70.0 (2025-03-31) Full Changelog: [v1.69.0...v1.70.0](https://github.com/openai/openai-python/compare/v1.69.0...v1.70.0) ### Features * **api:** add `get /responses/{response_id}/input_items` endpoint ([4c6a35d](https://github.com/openai/openai-python/commit/4c6a35dec65362a6a738c3387dae57bf8cbfcbb2)) ## 1.69.0 (2025-03-27) Full Changelog: [v1.68.2...v1.69.0](https://github.com/openai/openai-python/compare/v1.68.2...v1.69.0) ### Features * **api:** add `get /chat/completions` endpoint ([e6b8a42](https://github.com/openai/openai-python/commit/e6b8a42fc4286656cc86c2acd83692b170e77b68)) ### Bug Fixes * **audio:** correctly parse transcription stream events ([16a3a19](https://github.com/openai/openai-python/commit/16a3a195ff31f099fbe46043a12d2380c2c01f83)) ### Chores * add hash of OpenAPI spec/config inputs to .stats.yml ([515e1cd](https://github.com/openai/openai-python/commit/515e1cdd4a3109e5b29618df813656e17f22b52a)) * **api:** updates to supported Voice IDs ([#2261](https://github.com/openai/openai-python/issues/2261)) ([64956f9](https://github.com/openai/openai-python/commit/64956f9d9889b04380c7f5eb926509d1efd523e6)) * fix typos ([#2259](https://github.com/openai/openai-python/issues/2259)) ([6160de3](https://github.com/openai/openai-python/commit/6160de3e099f09c2d6ee5eeee4cbcc55b67a8f87)) ## 1.68.2 (2025-03-21) Full Changelog: [v1.68.1...v1.68.2](https://github.com/openai/openai-python/compare/v1.68.1...v1.68.2) ### Refactors * **package:** rename audio extra to voice_helpers ([2dd6cb8](https://github.com/openai/openai-python/commit/2dd6cb87489fe12c5e45128f44d985c3f49aba1d)) ## 1.68.1 (2025-03-21) Full Changelog: [v1.68.0...v1.68.1](https://github.com/openai/openai-python/compare/v1.68.0...v1.68.1) ### Bug Fixes * **client:** remove duplicate types ([#2235](https://github.com/openai/openai-python/issues/2235)) ([063f7d0](https://github.com/openai/openai-python/commit/063f7d0684c350ca9d766e2cb150233a22a623c8)) * **helpers/audio:** remove duplicative module ([f253d04](https://github.com/openai/openai-python/commit/f253d0415145f2c4904ea2e7b389d31d94e45a54)) * **package:** make sounddevice and numpy optional dependencies ([8b04453](https://github.com/openai/openai-python/commit/8b04453f0483736c13f0209a9f8f3618bc0e86c9)) ### Chores * **ci:** run workflows on next too ([67f89d4](https://github.com/openai/openai-python/commit/67f89d478aab780d1481c9bf6682c6633e431137)) ## 1.68.0 (2025-03-20) Full Changelog: [v1.67.0...v1.68.0](https://github.com/openai/openai-python/compare/v1.67.0...v1.68.0) ### Features * add audio helpers ([423655c](https://github.com/openai/openai-python/commit/423655ca9077cfd258f1e52f6eb386fc8307fa5f)) * **api:** new models for TTS, STT, + new audio features for Realtime ([#2232](https://github.com/openai/openai-python/issues/2232)) ([ab5192d](https://github.com/openai/openai-python/commit/ab5192d0a7b417ade622ec94dd48f86beb90692c)) ## 1.67.0 (2025-03-19) Full Changelog: [v1.66.5...v1.67.0](https://github.com/openai/openai-python/compare/v1.66.5...v1.67.0) ### Features * **api:** o1-pro now available through the API ([#2228](https://github.com/openai/openai-python/issues/2228)) ([40a19d8](https://github.com/openai/openai-python/commit/40a19d8592c1767d6318230fc93e37c360d1bcd1)) ## 1.66.5 (2025-03-18) Full Changelog: [v1.66.4...v1.66.5](https://github.com/openai/openai-python/compare/v1.66.4...v1.66.5) ### Bug Fixes * **types:** improve responses type names ([#2224](https://github.com/openai/openai-python/issues/2224)) ([5f7beb8](https://github.com/openai/openai-python/commit/5f7beb873af5ccef2551f34ab3ef098e099ce9c6)) ### Chores * **internal:** add back releases workflow ([c71d4c9](https://github.com/openai/openai-python/commit/c71d4c918eab3532b36ea944b0c4069db6ac2d38)) * **internal:** codegen related update ([#2222](https://github.com/openai/openai-python/issues/2222)) ([f570d91](https://github.com/openai/openai-python/commit/f570d914a16cb5092533e32dfd863027d378c0b5)) ## 1.66.4 (2025-03-17) Full Changelog: [v1.66.3...v1.66.4](https://github.com/openai/openai-python/compare/v1.66.3...v1.66.4) ### Bug Fixes * **ci:** ensure pip is always available ([#2207](https://github.com/openai/openai-python/issues/2207)) ([3f08e56](https://github.com/openai/openai-python/commit/3f08e56a48a04c2b7f03a4ad63f38228e25810e6)) * **ci:** remove publishing patch ([#2208](https://github.com/openai/openai-python/issues/2208)) ([dd2dab7](https://github.com/openai/openai-python/commit/dd2dab7faf2a003da3e6af66780bd250be6e7f3f)) * **types:** handle more discriminated union shapes ([#2206](https://github.com/openai/openai-python/issues/2206)) ([f85a9c6](https://github.com/openai/openai-python/commit/f85a9c633dcb9b64c0eb47d20151894742bbef22)) ### Chores * **internal:** bump rye to 0.44.0 ([#2200](https://github.com/openai/openai-python/issues/2200)) ([2dd3139](https://github.com/openai/openai-python/commit/2dd3139df6e7fe6307f9847e6527073e355e5047)) * **internal:** remove CI condition ([#2203](https://github.com/openai/openai-python/issues/2203)) ([9620fdc](https://github.com/openai/openai-python/commit/9620fdcf4f2d01b6753ecc0abc16e5239c2b41e1)) * **internal:** remove extra empty newlines ([#2195](https://github.com/openai/openai-python/issues/2195)) ([a1016a7](https://github.com/openai/openai-python/commit/a1016a78fe551e0f0e2562a0e81d1cb724d195da)) * **internal:** update release workflows ([e2def44](https://github.com/openai/openai-python/commit/e2def4453323aa1cf8077df447fd55eb4c626393)) ## 1.66.3 (2025-03-12) Full Changelog: [v1.66.2...v1.66.3](https://github.com/openai/openai-python/compare/v1.66.2...v1.66.3) ### Bug Fixes * update module level client ([#2185](https://github.com/openai/openai-python/issues/2185)) ([456f324](https://github.com/openai/openai-python/commit/456f3240a0c33e71521c6b73c32e8adc1b8cd3bc)) ## 1.66.2 (2025-03-11) Full Changelog: [v1.66.1...v1.66.2](https://github.com/openai/openai-python/compare/v1.66.1...v1.66.2) ### Bug Fixes * **responses:** correct reasoning output type ([#2181](https://github.com/openai/openai-python/issues/2181)) ([8cb1129](https://github.com/openai/openai-python/commit/8cb11299acc40c80061af275691cd09a2bf30c65)) ## 1.66.1 (2025-03-11) Full Changelog: [v1.66.0...v1.66.1](https://github.com/openai/openai-python/compare/v1.66.0...v1.66.1) ### Bug Fixes * **responses:** correct computer use enum value ([#2180](https://github.com/openai/openai-python/issues/2180)) ([48f4628](https://github.com/openai/openai-python/commit/48f4628c5fb18ddd7d71e8730184f3ac50c4ffea)) ### Chores * **internal:** temporary commit ([afabec1](https://github.com/openai/openai-python/commit/afabec1b5b18b41ac870970d06e6c2f152ef7bbe)) ## 1.66.0 (2025-03-11) Full Changelog: [v1.65.5...v1.66.0](https://github.com/openai/openai-python/compare/v1.65.5...v1.66.0) ### Features * **api:** add /v1/responses and built-in tools ([854df97](https://github.com/openai/openai-python/commit/854df97884736244d46060fd3d5a92916826ec8f)) ### Chores * export more types ([#2176](https://github.com/openai/openai-python/issues/2176)) ([a730f0e](https://github.com/openai/openai-python/commit/a730f0efedd228f96a49467f17fb19b6a219246c)) ## 1.65.5 (2025-03-09) Full Changelog: [v1.65.4...v1.65.5](https://github.com/openai/openai-python/compare/v1.65.4...v1.65.5) ### Chores * move ChatModel type to shared ([#2167](https://github.com/openai/openai-python/issues/2167)) ([104f02a](https://github.com/openai/openai-python/commit/104f02af371076d5d2498e48ae14d2eacc7df8bd)) ## 1.65.4 (2025-03-05) Full Changelog: [v1.65.3...v1.65.4](https://github.com/openai/openai-python/compare/v1.65.3...v1.65.4) ### Bug Fixes * **api:** add missing file rank enum + more metadata ([#2164](https://github.com/openai/openai-python/issues/2164)) ([0387e48](https://github.com/openai/openai-python/commit/0387e48e0880e496eb74b60eec9ed76a3171f14d)) ## 1.65.3 (2025-03-04) Full Changelog: [v1.65.2...v1.65.3](https://github.com/openai/openai-python/compare/v1.65.2...v1.65.3) ### Chores * **internal:** remove unused http client options forwarding ([#2158](https://github.com/openai/openai-python/issues/2158)) ([76ec464](https://github.com/openai/openai-python/commit/76ec464cfe3db3fa59a766259d6d6ee5bb889f86)) * **internal:** run example files in CI ([#2160](https://github.com/openai/openai-python/issues/2160)) ([9979345](https://github.com/openai/openai-python/commit/9979345038594440eec2f500c0c7cc5417cc7c08)) ## 1.65.2 (2025-03-01) Full Changelog: [v1.65.1...v1.65.2](https://github.com/openai/openai-python/compare/v1.65.1...v1.65.2) ### Bug Fixes * **azure:** azure_deployment use with realtime + non-deployment-based APIs ([#2154](https://github.com/openai/openai-python/issues/2154)) ([5846b55](https://github.com/openai/openai-python/commit/5846b552877f3d278689c521f9a26ce31167e1ea)) ### Chores * **docs:** update client docstring ([#2152](https://github.com/openai/openai-python/issues/2152)) ([0518c34](https://github.com/openai/openai-python/commit/0518c341ee0e19941c6b1d9d60e2552e1aa17f26)) ## 1.65.1 (2025-02-27) Full Changelog: [v1.65.0...v1.65.1](https://github.com/openai/openai-python/compare/v1.65.0...v1.65.1) ### Documentation * update URLs from stainlessapi.com to stainless.com ([#2150](https://github.com/openai/openai-python/issues/2150)) ([dee4298](https://github.com/openai/openai-python/commit/dee42986eff46dd23ba25b3e2a5bb7357aca39d9)) ## 1.65.0 (2025-02-27) Full Changelog: [v1.64.0...v1.65.0](https://github.com/openai/openai-python/compare/v1.64.0...v1.65.0) ### Features * **api:** add gpt-4.5-preview ([#2149](https://github.com/openai/openai-python/issues/2149)) ([4cee52e](https://github.com/openai/openai-python/commit/4cee52e8d191b0532f28d86446da79b43a58b907)) ### Chores * **internal:** properly set __pydantic_private__ ([#2144](https://github.com/openai/openai-python/issues/2144)) ([2b1bd16](https://github.com/openai/openai-python/commit/2b1bd1604a038ded67367742a0b1c9d92e29dfc8)) ## 1.64.0 (2025-02-22) Full Changelog: [v1.63.2...v1.64.0](https://github.com/openai/openai-python/compare/v1.63.2...v1.64.0) ### Features * **client:** allow passing `NotGiven` for body ([#2135](https://github.com/openai/openai-python/issues/2135)) ([4451f56](https://github.com/openai/openai-python/commit/4451f5677f9eaad9b8fee74f71c2e5fe6785c420)) ### Bug Fixes * **client:** mark some request bodies as optional ([4451f56](https://github.com/openai/openai-python/commit/4451f5677f9eaad9b8fee74f71c2e5fe6785c420)) ### Chores * **internal:** fix devcontainers setup ([#2137](https://github.com/openai/openai-python/issues/2137)) ([4d88402](https://github.com/openai/openai-python/commit/4d884020cbeb1ca6093dd5317e3e5812551f7a46)) ## 1.63.2 (2025-02-17) Full Changelog: [v1.63.1...v1.63.2](https://github.com/openai/openai-python/compare/v1.63.1...v1.63.2) ### Chores * **internal:** revert temporary commit ([#2121](https://github.com/openai/openai-python/issues/2121)) ([72458ab](https://github.com/openai/openai-python/commit/72458abeed3dd95db8aabed94a33bb12a916f8b7)) ## 1.63.1 (2025-02-17) Full Changelog: [v1.63.0...v1.63.1](https://github.com/openai/openai-python/compare/v1.63.0...v1.63.1) ### Chores * **internal:** temporary commit ([#2121](https://github.com/openai/openai-python/issues/2121)) ([f7f8361](https://github.com/openai/openai-python/commit/f7f83614c8da84c6725d60936f08f9f1a65f0a9e)) ## 1.63.0 (2025-02-13) Full Changelog: [v1.62.0...v1.63.0](https://github.com/openai/openai-python/compare/v1.62.0...v1.63.0) ### Features * **api:** add support for storing chat completions ([#2117](https://github.com/openai/openai-python/issues/2117)) ([2357a8f](https://github.com/openai/openai-python/commit/2357a8f97246a3fe17c6ac1fb0d7a67d6f1ffc1d)) ## 1.62.0 (2025-02-12) Full Changelog: [v1.61.1...v1.62.0](https://github.com/openai/openai-python/compare/v1.61.1...v1.62.0) ### Features * **client:** send `X-Stainless-Read-Timeout` header ([#2094](https://github.com/openai/openai-python/issues/2094)) ([0288213](https://github.com/openai/openai-python/commit/0288213fbfa935c9bf9d56416619ea929ae1cf63)) * **embeddings:** use stdlib array type for improved performance ([#2060](https://github.com/openai/openai-python/issues/2060)) ([9a95db9](https://github.com/openai/openai-python/commit/9a95db9154ac98678970e7f1652a7cacfd2f7fdb)) * **pagination:** avoid fetching when has_more: false ([#2098](https://github.com/openai/openai-python/issues/2098)) ([1882483](https://github.com/openai/openai-python/commit/18824832d3a676ae49206cd2b5e09d4796fdf033)) ### Bug Fixes * **api:** add missing reasoning effort + model enums ([#2096](https://github.com/openai/openai-python/issues/2096)) ([e0ca9f0](https://github.com/openai/openai-python/commit/e0ca9f0f6fae40230f8cab97573914ed632920b6)) * **parsing:** don't default to an empty array ([#2106](https://github.com/openai/openai-python/issues/2106)) ([8e748bb](https://github.com/openai/openai-python/commit/8e748bb08d9c0d1f7e8a1af31452e25eb7154f55)) ### Chores * **internal:** fix type traversing dictionary params ([#2097](https://github.com/openai/openai-python/issues/2097)) ([4e5b368](https://github.com/openai/openai-python/commit/4e5b368bf576f38d0f125778edde74ed6d101d7d)) * **internal:** minor type handling changes ([#2099](https://github.com/openai/openai-python/issues/2099)) ([a2c6da0](https://github.com/openai/openai-python/commit/a2c6da0fbc610ee80a2e044a0b20fc1cc2376962)) ## 1.61.1 (2025-02-05) Full Changelog: [v1.61.0...v1.61.1](https://github.com/openai/openai-python/compare/v1.61.0...v1.61.1) ### Bug Fixes * **api/types:** correct audio duration & role types ([#2091](https://github.com/openai/openai-python/issues/2091)) ([afcea48](https://github.com/openai/openai-python/commit/afcea4891ff85de165ccc2b5497ccf9a90520e9e)) * **cli/chat:** only send params when set ([#2077](https://github.com/openai/openai-python/issues/2077)) ([688b223](https://github.com/openai/openai-python/commit/688b223d9a733d241d50e5d7df62f346592c537c)) ### Chores * **internal:** bummp ruff dependency ([#2080](https://github.com/openai/openai-python/issues/2080)) ([b7a80b1](https://github.com/openai/openai-python/commit/b7a80b1994ab86e81485b88531e4aea63b3da594)) * **internal:** change default timeout to an int ([#2079](https://github.com/openai/openai-python/issues/2079)) ([d3df1c6](https://github.com/openai/openai-python/commit/d3df1c6ca090598701e38fd376a9796aadba88f1)) ## 1.61.0 (2025-01-31) Full Changelog: [v1.60.2...v1.61.0](https://github.com/openai/openai-python/compare/v1.60.2...v1.61.0) ### Features * **api:** add o3-mini ([#2067](https://github.com/openai/openai-python/issues/2067)) ([12b87a4](https://github.com/openai/openai-python/commit/12b87a4a1e6cb071a6b063d089585dec56a5d534)) ### Bug Fixes * **types:** correct metadata type + other fixes ([12b87a4](https://github.com/openai/openai-python/commit/12b87a4a1e6cb071a6b063d089585dec56a5d534)) ### Chores * **helpers:** section links ([ef8d3cc](https://github.com/openai/openai-python/commit/ef8d3cce40022d3482d341455be604e5f1afbd70)) * **types:** fix Metadata types ([82d3156](https://github.com/openai/openai-python/commit/82d3156e74ed2f95edd10cd7ebea53d2b5562794)) * update api.md ([#2063](https://github.com/openai/openai-python/issues/2063)) ([21964f0](https://github.com/openai/openai-python/commit/21964f00fb104011c4c357544114702052b74548)) ### Documentation * **readme:** current section links ([#2055](https://github.com/openai/openai-python/issues/2055)) ([ef8d3cc](https://github.com/openai/openai-python/commit/ef8d3cce40022d3482d341455be604e5f1afbd70)) ## 1.60.2 (2025-01-27) Full Changelog: [v1.60.1...v1.60.2](https://github.com/openai/openai-python/compare/v1.60.1...v1.60.2) ### Bug Fixes * **parsing:** don't validate input tools in the asynchronous `.parse()` method ([6fcfe73](https://github.com/openai/openai-python/commit/6fcfe73cd335853c7dd2cd3151a0d5d1785cfc9c)) ## 1.60.1 (2025-01-24) Full Changelog: [v1.60.0...v1.60.1](https://github.com/openai/openai-python/compare/v1.60.0...v1.60.1) ### Chores * **internal:** minor formatting changes ([#2050](https://github.com/openai/openai-python/issues/2050)) ([9c44192](https://github.com/openai/openai-python/commit/9c44192be5776d9252d36dc027a33c60b33d81b2)) ### Documentation * **examples/azure:** add async snippet ([#1787](https://github.com/openai/openai-python/issues/1787)) ([f60eda1](https://github.com/openai/openai-python/commit/f60eda1c1e8caf0ec2274b18b3fb2252304196db)) ## 1.60.0 (2025-01-22) Full Changelog: [v1.59.9...v1.60.0](https://github.com/openai/openai-python/compare/v1.59.9...v1.60.0) ### Features * **api:** update enum values, comments, and examples ([#2045](https://github.com/openai/openai-python/issues/2045)) ([e8205fd](https://github.com/openai/openai-python/commit/e8205fd58f0d677f476c577a8d9afb90f5710506)) ### Chores * **internal:** minor style changes ([#2043](https://github.com/openai/openai-python/issues/2043)) ([89a9dd8](https://github.com/openai/openai-python/commit/89a9dd821eaf5300ad11b0270b61fdfa4fd6e9b6)) ### Documentation * **readme:** mention failed requests in request IDs ([5f7c30b](https://github.com/openai/openai-python/commit/5f7c30bc006ffb666c324011a68aae357cb33e35)) ## 1.59.9 (2025-01-20) Full Changelog: [v1.59.8...v1.59.9](https://github.com/openai/openai-python/compare/v1.59.8...v1.59.9) ### Bug Fixes * **tests:** make test_get_platform less flaky ([#2040](https://github.com/openai/openai-python/issues/2040)) ([72ea05c](https://github.com/openai/openai-python/commit/72ea05cf18caaa7a5e6fe7e2251ab93fa0ba3140)) ### Chores * **internal:** avoid pytest-asyncio deprecation warning ([#2041](https://github.com/openai/openai-python/issues/2041)) ([b901046](https://github.com/openai/openai-python/commit/b901046ddda9c79b7f019e2263c02d126a3b2ee2)) * **internal:** update websockets dep ([#2036](https://github.com/openai/openai-python/issues/2036)) ([642cd11](https://github.com/openai/openai-python/commit/642cd119482c6fbca925ba702ad2579f9dc47bf9)) ### Documentation * fix typo ([#2031](https://github.com/openai/openai-python/issues/2031)) ([02fcf15](https://github.com/openai/openai-python/commit/02fcf15611953089826a74725cb96201d94658bb)) * **raw responses:** fix duplicate `the` ([#2039](https://github.com/openai/openai-python/issues/2039)) ([9b8eab9](https://github.com/openai/openai-python/commit/9b8eab99fdc6a581a1f5cc421c6f74b0e2b30415)) ## 1.59.8 (2025-01-17) Full Changelog: [v1.59.7...v1.59.8](https://github.com/openai/openai-python/compare/v1.59.7...v1.59.8) ### Bug Fixes * streaming ([c16f58e](https://github.com/openai/openai-python/commit/c16f58ead0bc85055b164182689ba74b7e939dfa)) * **structured outputs:** avoid parsing empty empty content ([#2023](https://github.com/openai/openai-python/issues/2023)) ([6d3513c](https://github.com/openai/openai-python/commit/6d3513c86f6e5800f8f73a45e089b7a205327121)) * **structured outputs:** correct schema coercion for inline ref expansion ([#2025](https://github.com/openai/openai-python/issues/2025)) ([2f4f0b3](https://github.com/openai/openai-python/commit/2f4f0b374207f162060c328b71ec995049dc42e8)) * **types:** correct type for vector store chunking strategy ([#2017](https://github.com/openai/openai-python/issues/2017)) ([e389279](https://github.com/openai/openai-python/commit/e38927950a5cdad99065853fe7b72aad6bb322e9)) ### Chores * **examples:** update realtime model ([f26746c](https://github.com/openai/openai-python/commit/f26746cbcd893d66cf8a3fd68a7c3779dc8c833c)), closes [#2020](https://github.com/openai/openai-python/issues/2020) * **internal:** bump pyright dependency ([#2021](https://github.com/openai/openai-python/issues/2021)) ([0a9a0f5](https://github.com/openai/openai-python/commit/0a9a0f5d8b9d5457643798287f893305006dd518)) * **internal:** streaming refactors ([#2012](https://github.com/openai/openai-python/issues/2012)) ([d76a748](https://github.com/openai/openai-python/commit/d76a748f606743407f94dfc26758095560e2082a)) * **internal:** update deps ([#2015](https://github.com/openai/openai-python/issues/2015)) ([514e0e4](https://github.com/openai/openai-python/commit/514e0e415f87ab4510262d29ed6125384e017b84)) ### Documentation * **examples/azure:** example script with realtime API ([#1967](https://github.com/openai/openai-python/issues/1967)) ([84f2f9c](https://github.com/openai/openai-python/commit/84f2f9c0439229a7db7136fe78419292d34d1f81)) ## 1.59.7 (2025-01-13) Full Changelog: [v1.59.6...v1.59.7](https://github.com/openai/openai-python/compare/v1.59.6...v1.59.7) ### Chores * export HttpxBinaryResponseContent class ([7191b71](https://github.com/openai/openai-python/commit/7191b71f3dcbbfcb2f2bec855c3bba93c956384e)) ## 1.59.6 (2025-01-09) Full Changelog: [v1.59.5...v1.59.6](https://github.com/openai/openai-python/compare/v1.59.5...v1.59.6) ### Bug Fixes * correctly handle deserialising `cls` fields ([#2002](https://github.com/openai/openai-python/issues/2002)) ([089c820](https://github.com/openai/openai-python/commit/089c820c8a5d20e9db6a171f0a4f11b481fe8465)) ### Chores * **internal:** spec update ([#2000](https://github.com/openai/openai-python/issues/2000)) ([36548f8](https://github.com/openai/openai-python/commit/36548f871763fdd7b5ce44903d186bc916331549)) ## 1.59.5 (2025-01-08) Full Changelog: [v1.59.4...v1.59.5](https://github.com/openai/openai-python/compare/v1.59.4...v1.59.5) ### Bug Fixes * **client:** only call .close() when needed ([#1992](https://github.com/openai/openai-python/issues/1992)) ([bdfd699](https://github.com/openai/openai-python/commit/bdfd699b99522e83f7610b5f98e36fe43ddf8338)) ### Documentation * fix typos ([#1995](https://github.com/openai/openai-python/issues/1995)) ([be694a0](https://github.com/openai/openai-python/commit/be694a097d6cf2668f08ecf94c882773b2ee1f84)) * fix typos ([#1996](https://github.com/openai/openai-python/issues/1996)) ([714aed9](https://github.com/openai/openai-python/commit/714aed9d7eb74a19f6e502fb6d4fe83399f82851)) * more typo fixes ([#1998](https://github.com/openai/openai-python/issues/1998)) ([7bd92f0](https://github.com/openai/openai-python/commit/7bd92f06a75f11f6afc2d1223d2426e186cc74cb)) * **readme:** moved period to inside parentheses ([#1980](https://github.com/openai/openai-python/issues/1980)) ([e7fae94](https://github.com/openai/openai-python/commit/e7fae948f2ba8db23461e4374308417570196847)) ## 1.59.4 (2025-01-07) Full Changelog: [v1.59.3...v1.59.4](https://github.com/openai/openai-python/compare/v1.59.3...v1.59.4) ### Chores * add missing isclass check ([#1988](https://github.com/openai/openai-python/issues/1988)) ([61d9072](https://github.com/openai/openai-python/commit/61d9072fbace58d64910ec7378c3686ac555972e)) * add missing isclass check for structured outputs ([bcbf013](https://github.com/openai/openai-python/commit/bcbf013e8d825b8b5f88172313dfb6e0313ca34c)) * **internal:** bump httpx dependency ([#1990](https://github.com/openai/openai-python/issues/1990)) ([288c2c3](https://github.com/openai/openai-python/commit/288c2c30dc405cbaa89924f9243442300e95e100)) ### Documentation * **realtime:** fix event reference link ([9b6885d](https://github.com/openai/openai-python/commit/9b6885d50f8d65ba5009642046727d291e0f14fa)) ## 1.59.3 (2025-01-03) Full Changelog: [v1.59.2...v1.59.3](https://github.com/openai/openai-python/compare/v1.59.2...v1.59.3) ### Chores * **api:** bump spec version ([#1985](https://github.com/openai/openai-python/issues/1985)) ([c6f1b35](https://github.com/openai/openai-python/commit/c6f1b357fcf669065f4ed6819d47a528b0787128)) ## 1.59.2 (2025-01-03) Full Changelog: [v1.59.1...v1.59.2](https://github.com/openai/openai-python/compare/v1.59.1...v1.59.2) ### Chores * **ci:** fix publish workflow ([0be1f5d](https://github.com/openai/openai-python/commit/0be1f5de0daf807cece564abf061c8bb188bb9aa)) * **internal:** empty commit ([fe8dc2e](https://github.com/openai/openai-python/commit/fe8dc2e97fc430ea2433ed28cfaa79425af223ec)) ## 1.59.1 (2025-01-02) Full Changelog: [v1.59.0...v1.59.1](https://github.com/openai/openai-python/compare/v1.59.0...v1.59.1) ### Chores * bump license year ([#1981](https://github.com/openai/openai-python/issues/1981)) ([f29011a](https://github.com/openai/openai-python/commit/f29011a6426d3fa4844ecd723ee20561ee60c665)) ## 1.59.0 (2024-12-21) Full Changelog: [v1.58.1...v1.59.0](https://github.com/openai/openai-python/compare/v1.58.1...v1.59.0) ### Features * **azure:** support for the Realtime API ([#1963](https://github.com/openai/openai-python/issues/1963)) ([9fda141](https://github.com/openai/openai-python/commit/9fda14172abdb66fe240aa7b4dc7cfae4faf1d73)) ### Chores * **realtime:** update docstrings ([#1964](https://github.com/openai/openai-python/issues/1964)) ([3dee863](https://github.com/openai/openai-python/commit/3dee863554d28272103e90a6a199ac196e92ff05)) ## 1.58.1 (2024-12-17) Full Changelog: [v1.58.0...v1.58.1](https://github.com/openai/openai-python/compare/v1.58.0...v1.58.1) ### Documentation * **readme:** fix example script link ([23ba877](https://github.com/openai/openai-python/commit/23ba8778fd55e0f54f36685e9c5950b452d8e10c)) ## 1.58.0 (2024-12-17) Full Changelog: [v1.57.4...v1.58.0](https://github.com/openai/openai-python/compare/v1.57.4...v1.58.0) ### Features * add Realtime API support ([#1958](https://github.com/openai/openai-python/issues/1958)) ([97d73cf](https://github.com/openai/openai-python/commit/97d73cf89935ca6098bb889a92f0ec2cdff16989)) * **api:** new o1 and GPT-4o models + preference fine-tuning ([#1956](https://github.com/openai/openai-python/issues/1956)) ([ec22ffb](https://github.com/openai/openai-python/commit/ec22ffb129c524525caa33b088405d27c271e631)) ### Bug Fixes * add reasoning_effort to all methods ([8829c32](https://github.com/openai/openai-python/commit/8829c3202dbe790ca3646476c802ec55ed47d864)) * **assistants:** correctly send `include` query param ([9a4c69c](https://github.com/openai/openai-python/commit/9a4c69c383bc6719b6521a485f2c7e62a9c036a9)) * **cli/migrate:** change grit binaries prefix ([#1951](https://github.com/openai/openai-python/issues/1951)) ([1c396c9](https://github.com/openai/openai-python/commit/1c396c95b040fb3d1a2523b09eaad4ff62d96846)) ### Chores * **internal:** fix some typos ([#1955](https://github.com/openai/openai-python/issues/1955)) ([628dead](https://github.com/openai/openai-python/commit/628dead660c00435bf46e09081c7b90b7bbe4a8a)) ### Documentation * add examples + guidance on Realtime API support ([1cb00f8](https://github.com/openai/openai-python/commit/1cb00f8fed78052aacbb9e0fac997b6ba0d44d2a)) * **readme:** example snippet for client context manager ([#1953](https://github.com/openai/openai-python/issues/1953)) ([ad80255](https://github.com/openai/openai-python/commit/ad802551d8aaf4e6eff711118676ec4e64392638)) ## 1.57.4 (2024-12-13) Full Changelog: [v1.57.3...v1.57.4](https://github.com/openai/openai-python/compare/v1.57.3...v1.57.4) ### Chores * **internal:** remove some duplicated imports ([#1946](https://github.com/openai/openai-python/issues/1946)) ([f94fddd](https://github.com/openai/openai-python/commit/f94fddd377015764b3c82919fdf956f619447b77)) * **internal:** updated imports ([#1948](https://github.com/openai/openai-python/issues/1948)) ([13971fc](https://github.com/openai/openai-python/commit/13971fc450106746c0ae02ab931e68b770ee105e)) ## 1.57.3 (2024-12-12) Full Changelog: [v1.57.2...v1.57.3](https://github.com/openai/openai-python/compare/v1.57.2...v1.57.3) ### Chores * **internal:** add support for TypeAliasType ([#1942](https://github.com/openai/openai-python/issues/1942)) ([d3442ff](https://github.com/openai/openai-python/commit/d3442ff28f2394200e14122f683d1f94686e8231)) * **internal:** bump pyright ([#1939](https://github.com/openai/openai-python/issues/1939)) ([190d1a8](https://github.com/openai/openai-python/commit/190d1a805dee7c37fb8f9dcb93b1715caa06cf95)) ## 1.57.2 (2024-12-10) Full Changelog: [v1.57.1...v1.57.2](https://github.com/openai/openai-python/compare/v1.57.1...v1.57.2) ### Bug Fixes * **azure:** handle trailing slash in `azure_endpoint` ([#1935](https://github.com/openai/openai-python/issues/1935)) ([69b73c5](https://github.com/openai/openai-python/commit/69b73c553b1982277c2f1b9d110ed951ddca689e)) ### Documentation * **readme:** fix http client proxies example ([#1932](https://github.com/openai/openai-python/issues/1932)) ([7a83e0f](https://github.com/openai/openai-python/commit/7a83e0fe4cc29e484ae417448b002c997745e4a3)) ## 1.57.1 (2024-12-09) Full Changelog: [v1.57.0...v1.57.1](https://github.com/openai/openai-python/compare/v1.57.0...v1.57.1) ### Chores * **internal:** bump pydantic dependency ([#1929](https://github.com/openai/openai-python/issues/1929)) ([5227c95](https://github.com/openai/openai-python/commit/5227c95eff9c7b1395e6d8f14b94652a91ed2ee2)) ## 1.57.0 (2024-12-05) Full Changelog: [v1.56.2...v1.57.0](https://github.com/openai/openai-python/compare/v1.56.2...v1.57.0) ### Features * **api:** updates ([#1924](https://github.com/openai/openai-python/issues/1924)) ([82ba614](https://github.com/openai/openai-python/commit/82ba6144682b0a6b3a22d4f764231c0c6afdcf6e)) ### Chores * bump openapi url ([#1922](https://github.com/openai/openai-python/issues/1922)) ([a472a8f](https://github.com/openai/openai-python/commit/a472a8fd0ba36b6897dcd02b6005fcf23f98f056)) ## 1.56.2 (2024-12-04) Full Changelog: [v1.56.1...v1.56.2](https://github.com/openai/openai-python/compare/v1.56.1...v1.56.2) ### Chores * make the `Omit` type public ([#1919](https://github.com/openai/openai-python/issues/1919)) ([4fb8a1c](https://github.com/openai/openai-python/commit/4fb8a1cf1f8df37ce8c027bbaaac85a648bae02a)) ## 1.56.1 (2024-12-03) Full Changelog: [v1.56.0...v1.56.1](https://github.com/openai/openai-python/compare/v1.56.0...v1.56.1) ### Bug Fixes * **cli:** remove usage of httpx proxies ([0e9fc3d](https://github.com/openai/openai-python/commit/0e9fc3dfbc7dec5b8c8f84dea9d87aad9f3d9cf6)) ### Chores * **internal:** bump pyright ([#1917](https://github.com/openai/openai-python/issues/1917)) ([0e87346](https://github.com/openai/openai-python/commit/0e8734637666ab22bc27fe4ec2cf7c39fddb5d08)) ## 1.56.0 (2024-12-02) Full Changelog: [v1.55.3...v1.56.0](https://github.com/openai/openai-python/compare/v1.55.3...v1.56.0) ### Features * **client:** make ChatCompletionStreamState public ([#1898](https://github.com/openai/openai-python/issues/1898)) ([dc7f6cb](https://github.com/openai/openai-python/commit/dc7f6cb2618686ff04bfdca228913cda3d320884)) ## 1.55.3 (2024-11-28) Full Changelog: [v1.55.2...v1.55.3](https://github.com/openai/openai-python/compare/v1.55.2...v1.55.3) ### Bug Fixes * **client:** compat with new httpx 0.28.0 release ([#1904](https://github.com/openai/openai-python/issues/1904)) ([72b6c63](https://github.com/openai/openai-python/commit/72b6c636c526885ef873580a07eff1c18e76bc10)) ## 1.55.2 (2024-11-27) Full Changelog: [v1.55.1...v1.55.2](https://github.com/openai/openai-python/compare/v1.55.1...v1.55.2) ### Chores * **internal:** exclude mypy from running on tests ([#1899](https://github.com/openai/openai-python/issues/1899)) ([e2496f1](https://github.com/openai/openai-python/commit/e2496f1d274126bdaa46a8256b3dd384b4ae244b)) ### Documentation * **assistants:** correct on_text_delta example ([#1896](https://github.com/openai/openai-python/issues/1896)) ([460b663](https://github.com/openai/openai-python/commit/460b663567ed1031467a8d69eb13fd3b3da38827)) ## 1.55.1 (2024-11-25) Full Changelog: [v1.55.0...v1.55.1](https://github.com/openai/openai-python/compare/v1.55.0...v1.55.1) ### Bug Fixes * **pydantic-v1:** avoid runtime error for assistants streaming ([#1885](https://github.com/openai/openai-python/issues/1885)) ([197c94b](https://github.com/openai/openai-python/commit/197c94b9e2620da8902aeed6959d2f871bb70461)) ### Chores * remove now unused `cached-property` dep ([#1867](https://github.com/openai/openai-python/issues/1867)) ([df5fac1](https://github.com/openai/openai-python/commit/df5fac1e557f79ed8d0935c48ca7f3f0bf77fa98)) * remove now unused `cached-property` dep ([#1891](https://github.com/openai/openai-python/issues/1891)) ([feebaae](https://github.com/openai/openai-python/commit/feebaae85d76960cb8f1c58dd9b5180136c47962)) ### Documentation * add info log level to readme ([#1887](https://github.com/openai/openai-python/issues/1887)) ([358255d](https://github.com/openai/openai-python/commit/358255d15ed220f8c80a3c0861b98e61e909a7ae)) ## 1.55.0 (2024-11-20) Full Changelog: [v1.54.5...v1.55.0](https://github.com/openai/openai-python/compare/v1.54.5...v1.55.0) ### Features * **api:** add gpt-4o-2024-11-20 model ([#1877](https://github.com/openai/openai-python/issues/1877)) ([ff64c2a](https://github.com/openai/openai-python/commit/ff64c2a0733854ed8cc1d7dd959a8287b2ec8120)) ## 1.54.5 (2024-11-19) Full Changelog: [v1.54.4...v1.54.5](https://github.com/openai/openai-python/compare/v1.54.4...v1.54.5) ### Bug Fixes * **asyncify:** avoid hanging process under certain conditions ([#1853](https://github.com/openai/openai-python/issues/1853)) ([3d23437](https://github.com/openai/openai-python/commit/3d234377e7c9cd19db5186688612eb18e68cec8f)) ### Chores * **internal:** minor test changes ([#1874](https://github.com/openai/openai-python/issues/1874)) ([189339d](https://github.com/openai/openai-python/commit/189339d2a09d23ea1883286972f366e19b397f91)) * **internal:** spec update ([#1873](https://github.com/openai/openai-python/issues/1873)) ([24c81f7](https://github.com/openai/openai-python/commit/24c81f729ae09ba3cec5542e5cc955c8b05b0f88)) * **tests:** limit array example length ([#1870](https://github.com/openai/openai-python/issues/1870)) ([1e550df](https://github.com/openai/openai-python/commit/1e550df708fc3b5d903b7adfa2180058a216b676)) ## 1.54.4 (2024-11-12) Full Changelog: [v1.54.3...v1.54.4](https://github.com/openai/openai-python/compare/v1.54.3...v1.54.4) ### Bug Fixes * don't use dicts as iterables in transform ([#1865](https://github.com/openai/openai-python/issues/1865)) ([76a51b1](https://github.com/openai/openai-python/commit/76a51b11efae50659a562197b1e18c6343964b56)) ### Documentation * bump models in example snippets to gpt-4o ([#1861](https://github.com/openai/openai-python/issues/1861)) ([adafe08](https://github.com/openai/openai-python/commit/adafe0859178d406fa93b38f3547f3d262651331)) * move comments in example snippets ([#1860](https://github.com/openai/openai-python/issues/1860)) ([362cf74](https://github.com/openai/openai-python/commit/362cf74d6c34506f98f6c4fb2304357be21f7691)) * **readme:** add missing asyncio import ([#1858](https://github.com/openai/openai-python/issues/1858)) ([dec9d0c](https://github.com/openai/openai-python/commit/dec9d0c97b702b6bcf9c71f5bdd6172bb5718354)) ## 1.54.3 (2024-11-06) Full Changelog: [v1.54.2...v1.54.3](https://github.com/openai/openai-python/compare/v1.54.2...v1.54.3) ### Bug Fixes * **logs:** redact sensitive headers ([#1850](https://github.com/openai/openai-python/issues/1850)) ([466608f](https://github.com/openai/openai-python/commit/466608fa56b7a9939c08a4c78be2f6fe4a05111b)) ## 1.54.2 (2024-11-06) Full Changelog: [v1.54.1...v1.54.2](https://github.com/openai/openai-python/compare/v1.54.1...v1.54.2) ### Chores * **tests:** adjust retry timeout values ([#1851](https://github.com/openai/openai-python/issues/1851)) ([cc8009c](https://github.com/openai/openai-python/commit/cc8009c9de56fe80f2689f69e7b891ff4ed297a3)) ## 1.54.1 (2024-11-05) Full Changelog: [v1.54.0...v1.54.1](https://github.com/openai/openai-python/compare/v1.54.0...v1.54.1) ### Bug Fixes * add new prediction param to all methods ([6aa424d](https://github.com/openai/openai-python/commit/6aa424d076098312801febd938bd4b5e8baf4851)) ## 1.54.0 (2024-11-04) Full Changelog: [v1.53.1...v1.54.0](https://github.com/openai/openai-python/compare/v1.53.1...v1.54.0) ### Features * **api:** add support for predicted outputs ([#1847](https://github.com/openai/openai-python/issues/1847)) ([42a4103](https://github.com/openai/openai-python/commit/42a410379a1b5f72424cc2e96dc6ddff22fd00be)) * **project:** drop support for Python 3.7 ([#1845](https://github.com/openai/openai-python/issues/1845)) ([0ed5b1a](https://github.com/openai/openai-python/commit/0ed5b1a9302ccf2f40c3c751cd777740a4749cda)) ## 1.53.1 (2024-11-04) Full Changelog: [v1.53.0...v1.53.1](https://github.com/openai/openai-python/compare/v1.53.0...v1.53.1) ### Bug Fixes * don't use dicts as iterables in transform ([#1842](https://github.com/openai/openai-python/issues/1842)) ([258f265](https://github.com/openai/openai-python/commit/258f26535744ab3b2f0746991fd29eae72ebd667)) * support json safe serialization for basemodel subclasses ([#1844](https://github.com/openai/openai-python/issues/1844)) ([2b80c90](https://github.com/openai/openai-python/commit/2b80c90c21d3b2468dfa3bf40c08c5b0e0eebffa)) ### Chores * **internal:** bump mypy ([#1839](https://github.com/openai/openai-python/issues/1839)) ([d92f959](https://github.com/openai/openai-python/commit/d92f959aa6f49be56574b4d1d1ac5ac48689dd46)) ## 1.53.0 (2024-10-30) Full Changelog: [v1.52.2...v1.53.0](https://github.com/openai/openai-python/compare/v1.52.2...v1.53.0) ### Features * **api:** add new, expressive voices for Realtime and Audio in Chat Completions ([7cf0a49](https://github.com/openai/openai-python/commit/7cf0a4958e4c985bef4d18bb919fa3948f389a82)) ### Chores * **internal:** bump pytest to v8 & pydantic ([#1829](https://github.com/openai/openai-python/issues/1829)) ([0e67a8a](https://github.com/openai/openai-python/commit/0e67a8af5daf9da029d2bd4bdf341cc8a494254a)) ## 1.52.2 (2024-10-23) Full Changelog: [v1.52.1...v1.52.2](https://github.com/openai/openai-python/compare/v1.52.1...v1.52.2) ### Chores * **internal:** update spec version ([#1816](https://github.com/openai/openai-python/issues/1816)) ([c23282a](https://github.com/openai/openai-python/commit/c23282a328c48af90a88673ff5f6cc7a866f8758)) ## 1.52.1 (2024-10-22) Full Changelog: [v1.52.0...v1.52.1](https://github.com/openai/openai-python/compare/v1.52.0...v1.52.1) ### Bug Fixes * **client/async:** correctly retry in all cases ([#1803](https://github.com/openai/openai-python/issues/1803)) ([9fe3f3f](https://github.com/openai/openai-python/commit/9fe3f3f925e06769b7ef6abbf1314a5e82749b4a)) ### Chores * **internal:** bump ruff dependency ([#1801](https://github.com/openai/openai-python/issues/1801)) ([859c672](https://github.com/openai/openai-python/commit/859c6725865f1b3285698f68693f9491d511f7ea)) * **internal:** remove unused black config ([#1807](https://github.com/openai/openai-python/issues/1807)) ([112dab0](https://github.com/openai/openai-python/commit/112dab0290342654265db612c37d327d652251bb)) * **internal:** update spec version ([#1810](https://github.com/openai/openai-python/issues/1810)) ([aa25b7b](https://github.com/openai/openai-python/commit/aa25b7b88823836b418a63da59491f5f3842773c)) * **internal:** update test syntax ([#1798](https://github.com/openai/openai-python/issues/1798)) ([d3098dd](https://github.com/openai/openai-python/commit/d3098dd0b9fbe627c21a8ad39c119d125b7cdb54)) * **tests:** add more retry tests ([#1806](https://github.com/openai/openai-python/issues/1806)) ([5525a1b](https://github.com/openai/openai-python/commit/5525a1ba536058ecc13411e1f98e88f7ec4bf8b9)) ## 1.52.0 (2024-10-17) Full Changelog: [v1.51.2...v1.52.0](https://github.com/openai/openai-python/compare/v1.51.2...v1.52.0) ### Features * **api:** add gpt-4o-audio-preview model for chat completions ([#1796](https://github.com/openai/openai-python/issues/1796)) ([fbf1e0c](https://github.com/openai/openai-python/commit/fbf1e0c25c4d163f06b61a43d1a94ce001033a7b)) ## 1.51.2 (2024-10-08) Full Changelog: [v1.51.1...v1.51.2](https://github.com/openai/openai-python/compare/v1.51.1...v1.51.2) ### Chores * add repr to PageInfo class ([#1780](https://github.com/openai/openai-python/issues/1780)) ([63118ee](https://github.com/openai/openai-python/commit/63118ee3c2481d217682e8a31337bdcc16893127)) ## 1.51.1 (2024-10-07) Full Changelog: [v1.51.0...v1.51.1](https://github.com/openai/openai-python/compare/v1.51.0...v1.51.1) ### Bug Fixes * **client:** avoid OverflowError with very large retry counts ([#1779](https://github.com/openai/openai-python/issues/1779)) ([fb1dacf](https://github.com/openai/openai-python/commit/fb1dacfa4d9447d123c38ab3d3d433d900d32ec5)) ### Chores * **internal:** add support for parsing bool response content ([#1774](https://github.com/openai/openai-python/issues/1774)) ([aa2e25f](https://github.com/openai/openai-python/commit/aa2e25f9a4a632357051397ea34d269eafba026d)) ### Documentation * fix typo in fenced code block language ([#1769](https://github.com/openai/openai-python/issues/1769)) ([57bbc15](https://github.com/openai/openai-python/commit/57bbc155210cc439a36f4e5cbd082e94c3349d78)) * improve and reference contributing documentation ([#1767](https://github.com/openai/openai-python/issues/1767)) ([a985a8b](https://github.com/openai/openai-python/commit/a985a8b8ab8d0b364bd3c26b6423a7c49ae7b1ce)) ## 1.51.0 (2024-10-01) Full Changelog: [v1.50.2...v1.51.0](https://github.com/openai/openai-python/compare/v1.50.2...v1.51.0) ### Features * **api:** support storing chat completions, enabling evals and model distillation in the dashboard ([2840c6d](https://github.com/openai/openai-python/commit/2840c6df94afb44cfd80efabe0405898331ee267)) ### Chores * **docs:** fix maxium typo ([#1762](https://github.com/openai/openai-python/issues/1762)) ([de94553](https://github.com/openai/openai-python/commit/de94553f93d71fc6c8187c8d3fbe924a71cc46dd)) * **internal:** remove ds store ([47a3968](https://github.com/openai/openai-python/commit/47a3968f9b318eb02d5602f5b10e7d9e69c3ae84)) ### Documentation * **helpers:** fix method name typo ([#1764](https://github.com/openai/openai-python/issues/1764)) ([e1bcfe8](https://github.com/openai/openai-python/commit/e1bcfe86554017ac63055060153c4fd72e65c0cf)) ## 1.50.2 (2024-09-27) Full Changelog: [v1.50.1...v1.50.2](https://github.com/openai/openai-python/compare/v1.50.1...v1.50.2) ### Bug Fixes * **audio:** correct types for transcriptions / translations ([#1755](https://github.com/openai/openai-python/issues/1755)) ([76c1f3f](https://github.com/openai/openai-python/commit/76c1f3f318b68003aae124c02efc4547a398a864)) ## 1.50.1 (2024-09-27) Full Changelog: [v1.50.0...v1.50.1](https://github.com/openai/openai-python/compare/v1.50.0...v1.50.1) ### Documentation * **helpers:** fix chat completion anchor ([#1753](https://github.com/openai/openai-python/issues/1753)) ([956d4e8](https://github.com/openai/openai-python/commit/956d4e8e32507fbce399f4619e06daa9d37a0532)) ## 1.50.0 (2024-09-26) Full Changelog: [v1.49.0...v1.50.0](https://github.com/openai/openai-python/compare/v1.49.0...v1.50.0) ### Features * **structured outputs:** add support for accessing raw responses ([#1748](https://github.com/openai/openai-python/issues/1748)) ([0189e28](https://github.com/openai/openai-python/commit/0189e28b0b062a28b16343da0460a4f0f4e17a9a)) ### Chores * **pydantic v1:** exclude specific properties when rich printing ([#1751](https://github.com/openai/openai-python/issues/1751)) ([af535ce](https://github.com/openai/openai-python/commit/af535ce6a523eca39438f117a3e55f16064567a9)) ## 1.49.0 (2024-09-26) Full Changelog: [v1.48.0...v1.49.0](https://github.com/openai/openai-python/compare/v1.48.0...v1.49.0) ### Features * **api:** add omni-moderation model ([#1750](https://github.com/openai/openai-python/issues/1750)) ([05b50da](https://github.com/openai/openai-python/commit/05b50da5428d5c7b5ea09626bcd88f8423762bf8)) ### Chores * **internal:** update test snapshots ([#1749](https://github.com/openai/openai-python/issues/1749)) ([42f054e](https://github.com/openai/openai-python/commit/42f054ee7afa8ce8316c2ecd90608a0f7e13bfdd)) ## 1.48.0 (2024-09-25) Full Changelog: [v1.47.1...v1.48.0](https://github.com/openai/openai-python/compare/v1.47.1...v1.48.0) ### Features * **client:** allow overriding retry count header ([#1745](https://github.com/openai/openai-python/issues/1745)) ([9f07d4d](https://github.com/openai/openai-python/commit/9f07d4dbd6f24108a1f5e0309037318858f5a229)) ### Bug Fixes * **audio:** correct response_format translations type ([#1743](https://github.com/openai/openai-python/issues/1743)) ([b912108](https://github.com/openai/openai-python/commit/b9121089c696bc943323e2e75d4706401d809aaa)) ### Chores * **internal:** use `typing_extensions.overload` instead of `typing` ([#1740](https://github.com/openai/openai-python/issues/1740)) ([2522bd5](https://github.com/openai/openai-python/commit/2522bd59f7b5e903e4fc856a4c5dbdbe66bba37f)) ## 1.47.1 (2024-09-23) Full Changelog: [v1.47.0...v1.47.1](https://github.com/openai/openai-python/compare/v1.47.0...v1.47.1) ### Bug Fixes * **pydantic v1:** avoid warnings error ([1e8e7d1](https://github.com/openai/openai-python/commit/1e8e7d1f01a4ab4153085bc20484a19613d993b3)) ## 1.47.0 (2024-09-20) Full Changelog: [v1.46.1...v1.47.0](https://github.com/openai/openai-python/compare/v1.46.1...v1.47.0) ### Features * **client:** send retry count header ([21b0c00](https://github.com/openai/openai-python/commit/21b0c0043406d81971f87455e5a48b17935dc346)) ### Chores * **types:** improve type name for embedding models ([#1730](https://github.com/openai/openai-python/issues/1730)) ([4b4eb2b](https://github.com/openai/openai-python/commit/4b4eb2b37877728d2124ad5651ceebf615c0ab28)) ## 1.46.1 (2024-09-19) Full Changelog: [v1.46.0...v1.46.1](https://github.com/openai/openai-python/compare/v1.46.0...v1.46.1) ### Bug Fixes * **client:** handle domains with underscores ([#1726](https://github.com/openai/openai-python/issues/1726)) ([cd194df](https://github.com/openai/openai-python/commit/cd194dfdc418a84589bd903357cba349e9ad3e78)) ### Chores * **streaming:** silence pydantic model_dump warnings ([#1722](https://github.com/openai/openai-python/issues/1722)) ([30f84b9](https://github.com/openai/openai-python/commit/30f84b96081ac37f60e40a75d765dbbf563b61b3)) ## 1.46.0 (2024-09-17) Full Changelog: [v1.45.1...v1.46.0](https://github.com/openai/openai-python/compare/v1.45.1...v1.46.0) ### Features * **client:** add ._request_id property to object responses ([#1707](https://github.com/openai/openai-python/issues/1707)) ([8b3da05](https://github.com/openai/openai-python/commit/8b3da05a35b33245aec98693a0540ace6218a61b)) ### Documentation * **readme:** add examples for chat with image content ([#1703](https://github.com/openai/openai-python/issues/1703)) ([192b8f2](https://github.com/openai/openai-python/commit/192b8f2b6a49f462e48c1442858931875524ab49)) ## 1.45.1 (2024-09-16) Full Changelog: [v1.45.0...v1.45.1](https://github.com/openai/openai-python/compare/v1.45.0...v1.45.1) ### Chores * **internal:** bump pyright / mypy version ([#1717](https://github.com/openai/openai-python/issues/1717)) ([351af85](https://github.com/openai/openai-python/commit/351af85c5b813391910301a5049edddc8c9e70dd)) * **internal:** bump ruff ([#1714](https://github.com/openai/openai-python/issues/1714)) ([aceaf64](https://github.com/openai/openai-python/commit/aceaf641eedd092ed42e4aaf031e8cfbf37e4212)) * **internal:** update spec link ([#1716](https://github.com/openai/openai-python/issues/1716)) ([ca58c7f](https://github.com/openai/openai-python/commit/ca58c7f83a7cede0367dec2500127573c9b00d1f)) ### Documentation * update CONTRIBUTING.md ([#1710](https://github.com/openai/openai-python/issues/1710)) ([4d45eb5](https://github.com/openai/openai-python/commit/4d45eb5eb794bcc5076c022be09e06fae103abcc)) ## 1.45.0 (2024-09-12) Full Changelog: [v1.44.1...v1.45.0](https://github.com/openai/openai-python/compare/v1.44.1...v1.45.0) ### Features * **api:** add o1 models ([#1708](https://github.com/openai/openai-python/issues/1708)) ([06bd42e](https://github.com/openai/openai-python/commit/06bd42e77121a6abd4826a79ce1848812d956576)) * **errors:** include completion in LengthFinishReasonError ([#1701](https://github.com/openai/openai-python/issues/1701)) ([b0e3256](https://github.com/openai/openai-python/commit/b0e32562aff9aceafec994d3b047f7c2a9f11524)) ### Bug Fixes * **types:** correctly mark stream discriminator as optional ([#1706](https://github.com/openai/openai-python/issues/1706)) ([80f02f9](https://github.com/openai/openai-python/commit/80f02f9e5f83fac9cd2f4172b733a92ad01399b2)) ## 1.44.1 (2024-09-09) Full Changelog: [v1.44.0...v1.44.1](https://github.com/openai/openai-python/compare/v1.44.0...v1.44.1) ### Chores * add docstrings to raw response properties ([#1696](https://github.com/openai/openai-python/issues/1696)) ([1d2a19b](https://github.com/openai/openai-python/commit/1d2a19b0e8acab54c35ef2171d33321943488fdc)) ### Documentation * **readme:** add section on determining installed version ([#1697](https://github.com/openai/openai-python/issues/1697)) ([0255735](https://github.com/openai/openai-python/commit/0255735930d9c657c78e85e7f03fd1eb98a1e378)) * **readme:** improve custom `base_url` example ([#1694](https://github.com/openai/openai-python/issues/1694)) ([05eec8a](https://github.com/openai/openai-python/commit/05eec8a0b7fcdc8651021f2e685214a353b861d1)) ## 1.44.0 (2024-09-06) Full Changelog: [v1.43.1...v1.44.0](https://github.com/openai/openai-python/compare/v1.43.1...v1.44.0) ### Features * **vector store:** improve chunking strategy type names ([#1690](https://github.com/openai/openai-python/issues/1690)) ([e82cd85](https://github.com/openai/openai-python/commit/e82cd85ac4962e36cb3b139c503069b56918688f)) ## 1.43.1 (2024-09-05) Full Changelog: [v1.43.0...v1.43.1](https://github.com/openai/openai-python/compare/v1.43.0...v1.43.1) ### Chores * pyproject.toml formatting changes ([#1687](https://github.com/openai/openai-python/issues/1687)) ([3387ede](https://github.com/openai/openai-python/commit/3387ede0b896788bf1197378b01941c75bd6e179)) ## 1.43.0 (2024-08-29) Full Changelog: [v1.42.0...v1.43.0](https://github.com/openai/openai-python/compare/v1.42.0...v1.43.0) ### Features * **api:** add file search result details to run steps ([#1681](https://github.com/openai/openai-python/issues/1681)) ([f5449c0](https://github.com/openai/openai-python/commit/f5449c07580ac9707f0387f86f4772fbf0a874b6)) ## 1.42.0 (2024-08-20) Full Changelog: [v1.41.1...v1.42.0](https://github.com/openai/openai-python/compare/v1.41.1...v1.42.0) ### Features * **parsing:** add support for pydantic dataclasses ([#1655](https://github.com/openai/openai-python/issues/1655)) ([101bee9](https://github.com/openai/openai-python/commit/101bee9844f725d2174796c3d09a58d3aa079fad)) ### Chores * **ci:** also run pydantic v1 tests ([#1666](https://github.com/openai/openai-python/issues/1666)) ([af2a1ca](https://github.com/openai/openai-python/commit/af2a1ca408a406098c6c79837aa3561b822e08ec)) ## 1.41.1 (2024-08-19) Full Changelog: [v1.41.0...v1.41.1](https://github.com/openai/openai-python/compare/v1.41.0...v1.41.1) ### Bug Fixes * **json schema:** remove `None` defaults ([#1663](https://github.com/openai/openai-python/issues/1663)) ([30215c1](https://github.com/openai/openai-python/commit/30215c15df613cf9c36cafd717af79158c9db3e5)) ### Chores * **client:** fix parsing union responses when non-json is returned ([#1665](https://github.com/openai/openai-python/issues/1665)) ([822c37d](https://github.com/openai/openai-python/commit/822c37de49eb2ffe8c05122f7520ba87bd76e30b)) ## 1.41.0 (2024-08-16) Full Changelog: [v1.40.8...v1.41.0](https://github.com/openai/openai-python/compare/v1.40.8...v1.41.0) ### Features * **client:** add uploads.upload_file helper ([aae079d](https://github.com/openai/openai-python/commit/aae079daa3c1763ab0e46bad766ae5261b475806)) ## 1.40.8 (2024-08-15) Full Changelog: [v1.40.7...v1.40.8](https://github.com/openai/openai-python/compare/v1.40.7...v1.40.8) ### Chores * **types:** define FilePurpose enum ([#1653](https://github.com/openai/openai-python/issues/1653)) ([3c2eeae](https://github.com/openai/openai-python/commit/3c2eeae32adf5d4ab6bc622be6f9a95a1a298dd3)) ## 1.40.7 (2024-08-15) Full Changelog: [v1.40.6...v1.40.7](https://github.com/openai/openai-python/compare/v1.40.6...v1.40.7) ### Bug Fixes * **cli/migrate:** change grit binaries download source ([#1649](https://github.com/openai/openai-python/issues/1649)) ([85e8935](https://github.com/openai/openai-python/commit/85e8935d9a123b92964d39a98334a975a06ab845)) ### Chores * **docs:** fix typo in example snippet ([4e83b57](https://github.com/openai/openai-python/commit/4e83b57ffbb64e1c98c19968557dc68a0b65d0b3)) * **internal:** use different 32bit detection method ([#1652](https://github.com/openai/openai-python/issues/1652)) ([5831af6](https://github.com/openai/openai-python/commit/5831af65048af2a5df9e3ea4a48b8fff2e66dd8c)) ## 1.40.6 (2024-08-12) Full Changelog: [v1.40.5...v1.40.6](https://github.com/openai/openai-python/compare/v1.40.5...v1.40.6) ### Chores * **examples:** minor formatting changes ([#1644](https://github.com/openai/openai-python/issues/1644)) ([e08acf1](https://github.com/openai/openai-python/commit/e08acf1c6edd1501ed70c4634cd884ab1658af0d)) * **internal:** update some imports ([#1642](https://github.com/openai/openai-python/issues/1642)) ([fce1ea7](https://github.com/openai/openai-python/commit/fce1ea72a89ba2737bc77775fe04f3a21ecb28e7)) * sync openapi url ([#1646](https://github.com/openai/openai-python/issues/1646)) ([8ae3801](https://github.com/openai/openai-python/commit/8ae380123ada0bfaca9961e222a0e9c8b585e2d4)) * **tests:** fix pydantic v1 tests ([2623630](https://github.com/openai/openai-python/commit/26236303f0f6de5df887e8ee3e41d5bc39a3abb1)) ## 1.40.5 (2024-08-12) Full Changelog: [v1.40.4...v1.40.5](https://github.com/openai/openai-python/compare/v1.40.4...v1.40.5) ### Documentation * **helpers:** make async client usage more clear ([34e1edf](https://github.com/openai/openai-python/commit/34e1edf29d6008df7196aaebc45172fa536c6410)), closes [#1639](https://github.com/openai/openai-python/issues/1639) ## 1.40.4 (2024-08-12) Full Changelog: [v1.40.3...v1.40.4](https://github.com/openai/openai-python/compare/v1.40.3...v1.40.4) ### Bug Fixes * **json schema:** unravel `$ref`s alongside additional keys ([c7a3d29](https://github.com/openai/openai-python/commit/c7a3d2986acaf3b31844b39608d03265ad87bb04)) * **json schema:** unwrap `allOf`s with one entry ([53d964d](https://github.com/openai/openai-python/commit/53d964defebdf385d7d832ec7f13111b4af13c27)) ## 1.40.3 (2024-08-10) Full Changelog: [v1.40.2...v1.40.3](https://github.com/openai/openai-python/compare/v1.40.2...v1.40.3) ### Chores * **ci:** bump prism mock server version ([#1630](https://github.com/openai/openai-python/issues/1630)) ([214d8fd](https://github.com/openai/openai-python/commit/214d8fd8d7d43c06c7dfe02680847a6a60988120)) * **ci:** codeowners file ([#1627](https://github.com/openai/openai-python/issues/1627)) ([c059a20](https://github.com/openai/openai-python/commit/c059a20c8cd2124178641c9d8688e276b1cf1d59)) * **internal:** ensure package is importable in lint cmd ([#1631](https://github.com/openai/openai-python/issues/1631)) ([779e6d0](https://github.com/openai/openai-python/commit/779e6d081eb55c158f2aa1962190079eb7f1335e)) ## 1.40.2 (2024-08-08) Full Changelog: [v1.40.1...v1.40.2](https://github.com/openai/openai-python/compare/v1.40.1...v1.40.2) ### Bug Fixes * **client:** raise helpful error message for response_format misuse ([18191da](https://github.com/openai/openai-python/commit/18191dac8e1437a0f708525d474b7ecfe459d966)) * **json schema:** support recursive BaseModels in Pydantic v1 ([#1623](https://github.com/openai/openai-python/issues/1623)) ([43e10c0](https://github.com/openai/openai-python/commit/43e10c0f251a42f1e6497f360c6c23d3058b3da3)) ### Chores * **internal:** format some docstrings ([d34a081](https://github.com/openai/openai-python/commit/d34a081c30f869646145919b2256ded115241eb5)) * **internal:** updates ([#1624](https://github.com/openai/openai-python/issues/1624)) ([598e7a2](https://github.com/openai/openai-python/commit/598e7a23768e7addbe1319ada2e87caee3cf0d14)) ## 1.40.1 (2024-08-07) Full Changelog: [v1.40.0...v1.40.1](https://github.com/openai/openai-python/compare/v1.40.0...v1.40.1) ### Chores * **internal:** update OpenAPI spec url ([#1608](https://github.com/openai/openai-python/issues/1608)) ([5392753](https://github.com/openai/openai-python/commit/53927531fc101e96b9e3f5d44f34b298055f496a)) * **internal:** update test snapshots ([a11d1cb](https://github.com/openai/openai-python/commit/a11d1cb5d04aac0bf69dc10a3a21fa95575c0aa0)) ## 1.40.0 (2024-08-06) Full Changelog: [v1.39.0...v1.40.0](https://github.com/openai/openai-python/compare/v1.39.0...v1.40.0) ### Features * **api:** add structured outputs support ([e8dba7d](https://github.com/openai/openai-python/commit/e8dba7d0e08a7d0de5952be716e0efe9ae373759)) ### Chores * **internal:** bump ruff version ([#1604](https://github.com/openai/openai-python/issues/1604)) ([3e19a87](https://github.com/openai/openai-python/commit/3e19a87255d8e92716689656afaa3f16297773b6)) * **internal:** update pydantic compat helper function ([#1607](https://github.com/openai/openai-python/issues/1607)) ([973c18b](https://github.com/openai/openai-python/commit/973c18b259a0e4a8134223f50a5f660b86650949)) ## 1.39.0 (2024-08-05) Full Changelog: [v1.38.0...v1.39.0](https://github.com/openai/openai-python/compare/v1.38.0...v1.39.0) ### Features * **client:** add `retries_taken` to raw response class ([#1601](https://github.com/openai/openai-python/issues/1601)) ([777822b](https://github.com/openai/openai-python/commit/777822b39b7f9ebd6272d0af8fc04f9d657bd886)) ### Bug Fixes * **assistants:** add parallel_tool_calls param to runs.stream ([113e82a](https://github.com/openai/openai-python/commit/113e82a82c7390660ad3324fa8f9842f83b27571)) ### Chores * **internal:** bump pyright ([#1599](https://github.com/openai/openai-python/issues/1599)) ([27f0f10](https://github.com/openai/openai-python/commit/27f0f107e39d16adc0d5a50ffe4c687e0e3c42e5)) * **internal:** test updates ([#1602](https://github.com/openai/openai-python/issues/1602)) ([af22d80](https://github.com/openai/openai-python/commit/af22d8079cf44cde5f03a206e78b900f8413dc43)) * **internal:** use `TypeAlias` marker for type assignments ([#1597](https://github.com/openai/openai-python/issues/1597)) ([5907ea0](https://github.com/openai/openai-python/commit/5907ea04d6f5e0ffd17c38ad6a644a720ece8abe)) ## 1.38.0 (2024-08-02) Full Changelog: [v1.37.2...v1.38.0](https://github.com/openai/openai-python/compare/v1.37.2...v1.38.0) ### Features * extract out `ImageModel`, `AudioModel`, `SpeechModel` ([#1586](https://github.com/openai/openai-python/issues/1586)) ([b800316](https://github.com/openai/openai-python/commit/b800316aee6c8b2aeb609ca4c41972adccd2fa7a)) * make enums not nominal ([#1588](https://github.com/openai/openai-python/issues/1588)) ([ab4519b](https://github.com/openai/openai-python/commit/ab4519bc45f5512c8c5165641c217385d999809c)) ## 1.37.2 (2024-08-01) Full Changelog: [v1.37.1...v1.37.2](https://github.com/openai/openai-python/compare/v1.37.1...v1.37.2) ### Chores * **internal:** add type construction helper ([#1584](https://github.com/openai/openai-python/issues/1584)) ([cbb186a](https://github.com/openai/openai-python/commit/cbb186a534b520fa5b11a9b371b175e3f6a6482b)) * **runs/create_and_poll:** add parallel_tool_calls request param ([04b3e6c](https://github.com/openai/openai-python/commit/04b3e6c39ee5a7088e0e4dfa4c06f3dcce901a57)) ## 1.37.1 (2024-07-25) Full Changelog: [v1.37.0...v1.37.1](https://github.com/openai/openai-python/compare/v1.37.0...v1.37.1) ### Chores * **tests:** update prism version ([#1572](https://github.com/openai/openai-python/issues/1572)) ([af82593](https://github.com/openai/openai-python/commit/af8259393673af1ef6ec711da6297eb4ad55b66e)) ## 1.37.0 (2024-07-22) Full Changelog: [v1.36.1...v1.37.0](https://github.com/openai/openai-python/compare/v1.36.1...v1.37.0) ### Features * **api:** add uploads endpoints ([#1568](https://github.com/openai/openai-python/issues/1568)) ([d877b6d](https://github.com/openai/openai-python/commit/d877b6dabb9b3e8da6ff2f46de1120af54de398d)) ### Bug Fixes * **cli/audio:** handle non-json response format ([#1557](https://github.com/openai/openai-python/issues/1557)) ([bb7431f](https://github.com/openai/openai-python/commit/bb7431f602602d4c74d75809c6934a7fd192972d)) ### Documentation * **readme:** fix example snippet imports ([#1569](https://github.com/openai/openai-python/issues/1569)) ([0c90af6](https://github.com/openai/openai-python/commit/0c90af6412b3314c2257b9b8eb7fabd767f32ef6)) ## 1.36.1 (2024-07-20) Full Changelog: [v1.36.0...v1.36.1](https://github.com/openai/openai-python/compare/v1.36.0...v1.36.1) ### Bug Fixes * **types:** add gpt-4o-mini to more assistants methods ([39a8a37](https://github.com/openai/openai-python/commit/39a8a372eb3f2d75fd4310d42294d05175a59fd8)) ## 1.36.0 (2024-07-19) Full Changelog: [v1.35.15...v1.36.0](https://github.com/openai/openai-python/compare/v1.35.15...v1.36.0) ### Features * **api:** add new gpt-4o-mini models ([#1561](https://github.com/openai/openai-python/issues/1561)) ([5672ad4](https://github.com/openai/openai-python/commit/5672ad40aaa3498f6143baa48fc22bb1a3475bea)) ## 1.35.15 (2024-07-18) Full Changelog: [v1.35.14...v1.35.15](https://github.com/openai/openai-python/compare/v1.35.14...v1.35.15) ### Chores * **docs:** document how to do per-request http client customization ([#1560](https://github.com/openai/openai-python/issues/1560)) ([24c0768](https://github.com/openai/openai-python/commit/24c076873c5cb2abe0d3e285b99aa110451b0f19)) * **internal:** update formatting ([#1553](https://github.com/openai/openai-python/issues/1553)) ([e1389bc](https://github.com/openai/openai-python/commit/e1389bcc26f3aac63fc6bc9bb151c9a330d95b4e)) ## 1.35.14 (2024-07-15) Full Changelog: [v1.35.13...v1.35.14](https://github.com/openai/openai-python/compare/v1.35.13...v1.35.14) ### Chores * **docs:** minor update to formatting of API link in README ([#1550](https://github.com/openai/openai-python/issues/1550)) ([a6e59c6](https://github.com/openai/openai-python/commit/a6e59c6bbff9e1132aa323c0ecb3be7f0692ae42)) * **internal:** minor formatting changes ([ee1c62e](https://github.com/openai/openai-python/commit/ee1c62ede01872e76156d886af4aab5f8eb1cc64)) * **internal:** minor options / compat functions updates ([#1549](https://github.com/openai/openai-python/issues/1549)) ([a0701b5](https://github.com/openai/openai-python/commit/a0701b5dbeda4ac2d8a4b093aee4bdad9d674ee2)) ## 1.35.13 (2024-07-10) Full Changelog: [v1.35.12...v1.35.13](https://github.com/openai/openai-python/compare/v1.35.12...v1.35.13) ### Bug Fixes * **threads/runs/create_and_run_stream:** correct tool_resources param ([8effd08](https://github.com/openai/openai-python/commit/8effd08be3ab1cf509bdbfd9f174f9186fdbf71f)) ### Chores * **internal:** add helper function ([#1538](https://github.com/openai/openai-python/issues/1538)) ([81655a0](https://github.com/openai/openai-python/commit/81655a012e28c0240e71cf74b77ad1f9ac630906)) ## 1.35.12 (2024-07-09) Full Changelog: [v1.35.11...v1.35.12](https://github.com/openai/openai-python/compare/v1.35.11...v1.35.12) ### Bug Fixes * **azure:** refresh auth token during retries ([#1533](https://github.com/openai/openai-python/issues/1533)) ([287926e](https://github.com/openai/openai-python/commit/287926e4c0920b930af2b9d3d8b46a24e78e2979)) * **tests:** fresh_env() now resets new environment values ([64da888](https://github.com/openai/openai-python/commit/64da888ca4d13f0b4b6d9e22ec93a897b2d6bb24)) ## 1.35.11 (2024-07-09) Full Changelog: [v1.35.10...v1.35.11](https://github.com/openai/openai-python/compare/v1.35.10...v1.35.11) ### Chores * **internal:** minor request options handling changes ([#1534](https://github.com/openai/openai-python/issues/1534)) ([8b0e493](https://github.com/openai/openai-python/commit/8b0e49302b3fcc32cf02393bf28354c577188904)) ## 1.35.10 (2024-07-03) Full Changelog: [v1.35.9...v1.35.10](https://github.com/openai/openai-python/compare/v1.35.9...v1.35.10) ### Chores * **ci:** update rye to v0.35.0 ([#1523](https://github.com/openai/openai-python/issues/1523)) ([dd118c4](https://github.com/openai/openai-python/commit/dd118c422019df00b153104b7bddf892c2ec7417)) ## 1.35.9 (2024-07-02) Full Changelog: [v1.35.8...v1.35.9](https://github.com/openai/openai-python/compare/v1.35.8...v1.35.9) ### Bug Fixes * **client:** always respect content-type multipart/form-data if provided ([#1519](https://github.com/openai/openai-python/issues/1519)) ([6da55e1](https://github.com/openai/openai-python/commit/6da55e10c4ba8c78687baedc68d5599ea120d05c)) ### Chores * minor change to tests ([#1521](https://github.com/openai/openai-python/issues/1521)) ([a679c0b](https://github.com/openai/openai-python/commit/a679c0bd1e041434440174daa7a64289746856d1)) ## 1.35.8 (2024-07-02) Full Changelog: [v1.35.7...v1.35.8](https://github.com/openai/openai-python/compare/v1.35.7...v1.35.8) ### Chores * gitignore test server logs ([#1509](https://github.com/openai/openai-python/issues/1509)) ([936d840](https://github.com/openai/openai-python/commit/936d84094a28ad0a2b4a20e2b3bbf1674048223e)) * **internal:** add helper method for constructing `BaseModel`s ([#1517](https://github.com/openai/openai-python/issues/1517)) ([e5ddbf5](https://github.com/openai/openai-python/commit/e5ddbf554ce4b6be4b59114a36e69f02ca724acf)) * **internal:** add reflection helper function ([#1508](https://github.com/openai/openai-python/issues/1508)) ([6044e1b](https://github.com/openai/openai-python/commit/6044e1bbfa9e46a01faf5a9edf198f86fa4c6dd0)) * **internal:** add rich as a dev dependency ([#1514](https://github.com/openai/openai-python/issues/1514)) ([8a2b4e4](https://github.com/openai/openai-python/commit/8a2b4e4c1233dca916531ebc65d65a8d35fa7b7b)) ## 1.35.7 (2024-06-27) Full Changelog: [v1.35.6...v1.35.7](https://github.com/openai/openai-python/compare/v1.35.6...v1.35.7) ### Bug Fixes * **build:** include more files in sdist builds ([#1504](https://github.com/openai/openai-python/issues/1504)) ([730c1b5](https://github.com/openai/openai-python/commit/730c1b53b1a61e218a85aa2d1cf3ba4775618755)) ## 1.35.6 (2024-06-27) Full Changelog: [v1.35.5...v1.35.6](https://github.com/openai/openai-python/compare/v1.35.5...v1.35.6) ### Documentation * **readme:** improve some wording ([#1392](https://github.com/openai/openai-python/issues/1392)) ([a58a052](https://github.com/openai/openai-python/commit/a58a05215b560ebcf3ff3eb1dd997259720a48f3)) ## 1.35.5 (2024-06-26) Full Changelog: [v1.35.4...v1.35.5](https://github.com/openai/openai-python/compare/v1.35.4...v1.35.5) ### Bug Fixes * **cli/migrate:** avoid reliance on Python 3.12 argument ([be7a06b](https://github.com/openai/openai-python/commit/be7a06b3875e3ecb9229d67a41e290ca218f092d)) ## 1.35.4 (2024-06-26) Full Changelog: [v1.35.3...v1.35.4](https://github.com/openai/openai-python/compare/v1.35.3...v1.35.4) ### Bug Fixes * **docs:** fix link to advanced python httpx docs ([#1499](https://github.com/openai/openai-python/issues/1499)) ([cf45cd5](https://github.com/openai/openai-python/commit/cf45cd5942cecec569072146673ddfc0e0ec108e)) * temporarily patch upstream version to fix broken release flow ([#1500](https://github.com/openai/openai-python/issues/1500)) ([4f10470](https://github.com/openai/openai-python/commit/4f10470f5f74fc258a78fa6d897d8ab5b70dcf52)) ### Chores * **doc:** clarify service tier default value ([#1496](https://github.com/openai/openai-python/issues/1496)) ([ba39667](https://github.com/openai/openai-python/commit/ba39667c4faa8e10457347be41334ca9639186d4)) ## 1.35.3 (2024-06-20) Full Changelog: [v1.35.2...v1.35.3](https://github.com/openai/openai-python/compare/v1.35.2...v1.35.3) ### Bug Fixes * **tests:** add explicit type annotation ([9345f10](https://github.com/openai/openai-python/commit/9345f104889056b2ef6646d65375925a0a3bae03)) ## 1.35.2 (2024-06-20) Full Changelog: [v1.35.1...v1.35.2](https://github.com/openai/openai-python/compare/v1.35.1...v1.35.2) ### Bug Fixes * **api:** add missing parallel_tool_calls arguments ([4041e4f](https://github.com/openai/openai-python/commit/4041e4f6ea1e2316179a82031001308be23a2524)) ## 1.35.1 (2024-06-19) Full Changelog: [v1.35.0...v1.35.1](https://github.com/openai/openai-python/compare/v1.35.0...v1.35.1) ### Bug Fixes * **client/async:** avoid blocking io call for platform headers ([#1488](https://github.com/openai/openai-python/issues/1488)) ([ae64c05](https://github.com/openai/openai-python/commit/ae64c05cbae76a58b592d913bee6ac1ef9611d4c)) ## 1.35.0 (2024-06-18) Full Changelog: [v1.34.0...v1.35.0](https://github.com/openai/openai-python/compare/v1.34.0...v1.35.0) ### Features * **api:** add service tier argument for chat completions ([#1486](https://github.com/openai/openai-python/issues/1486)) ([b4b4e66](https://github.com/openai/openai-python/commit/b4b4e660b8bb7ae937787fcab9b40feaeba7f711)) ## 1.34.0 (2024-06-12) Full Changelog: [v1.33.0...v1.34.0](https://github.com/openai/openai-python/compare/v1.33.0...v1.34.0) ### Features * **api:** updates ([#1481](https://github.com/openai/openai-python/issues/1481)) ([b83db36](https://github.com/openai/openai-python/commit/b83db362f0c9a5a4d55588b954fb1df1a68c98e3)) ## 1.33.0 (2024-06-07) Full Changelog: [v1.32.1...v1.33.0](https://github.com/openai/openai-python/compare/v1.32.1...v1.33.0) ### Features * **api:** adding chunking_strategy to polling helpers ([#1478](https://github.com/openai/openai-python/issues/1478)) ([83be2a1](https://github.com/openai/openai-python/commit/83be2a13e0384d3de52190d86ccb1b5d7a197d84)) ## 1.32.1 (2024-06-07) Full Changelog: [v1.32.0...v1.32.1](https://github.com/openai/openai-python/compare/v1.32.0...v1.32.1) ### Bug Fixes * remove erroneous thread create argument ([#1476](https://github.com/openai/openai-python/issues/1476)) ([43175c4](https://github.com/openai/openai-python/commit/43175c40e607d626a77a151691778c35a0e60eec)) ## 1.32.0 (2024-06-06) Full Changelog: [v1.31.2...v1.32.0](https://github.com/openai/openai-python/compare/v1.31.2...v1.32.0) ### Features * **api:** updates ([#1474](https://github.com/openai/openai-python/issues/1474)) ([87ddff0](https://github.com/openai/openai-python/commit/87ddff0e6e64650691a8e32f7477b7a00e06ed23)) ## 1.31.2 (2024-06-06) Full Changelog: [v1.31.1...v1.31.2](https://github.com/openai/openai-python/compare/v1.31.1...v1.31.2) ### Chores * **internal:** minor refactor of tests ([#1471](https://github.com/openai/openai-python/issues/1471)) ([b7f2298](https://github.com/openai/openai-python/commit/b7f229866f249d16e995db361b923bb4c0b7f1d4)) ## 1.31.1 (2024-06-05) Full Changelog: [v1.31.0...v1.31.1](https://github.com/openai/openai-python/compare/v1.31.0...v1.31.1) ### Chores * **internal:** minor change to tests ([#1466](https://github.com/openai/openai-python/issues/1466)) ([cb33e71](https://github.com/openai/openai-python/commit/cb33e7152f25fb16cf4c39a6e4714169c62d6af8)) ## 1.31.0 (2024-06-03) Full Changelog: [v1.30.5...v1.31.0](https://github.com/openai/openai-python/compare/v1.30.5...v1.31.0) ### Features * **api:** updates ([#1461](https://github.com/openai/openai-python/issues/1461)) ([0d7cc5e](https://github.com/openai/openai-python/commit/0d7cc5e48c565fe10ee6e8ca4d050175eb543bcb)) ### Chores * fix lint ([1886dd4](https://github.com/openai/openai-python/commit/1886dd4c98d7a7b3a679bff739cb38badf5ae96c)) ## 1.30.5 (2024-05-29) Full Changelog: [v1.30.4...v1.30.5](https://github.com/openai/openai-python/compare/v1.30.4...v1.30.5) ### Chores * **internal:** fix lint issue ([35a1e80](https://github.com/openai/openai-python/commit/35a1e806891c34d5cc13ac8341751e5b15b52319)) ## 1.30.4 (2024-05-28) Full Changelog: [v1.30.3...v1.30.4](https://github.com/openai/openai-python/compare/v1.30.3...v1.30.4) ### Chores * add missing __all__ definitions ([7fba60f](https://github.com/openai/openai-python/commit/7fba60f2e8adc26e83080aaf3e436eb9891e1253)) * **internal:** fix lint issue ([f423cd0](https://github.com/openai/openai-python/commit/f423cd05d33b3e734eda7c0c008faac14ae96bb7)) ## 1.30.3 (2024-05-24) Full Changelog: [v1.30.2...v1.30.3](https://github.com/openai/openai-python/compare/v1.30.2...v1.30.3) ### Chores * **ci:** update rye install location ([#1440](https://github.com/openai/openai-python/issues/1440)) ([8a0e5bf](https://github.com/openai/openai-python/commit/8a0e5bf4c03d9c714799fad43be68ac9c2b1f37a)) * **internal:** bump pyright ([#1442](https://github.com/openai/openai-python/issues/1442)) ([64a151e](https://github.com/openai/openai-python/commit/64a151eae705d55484f870df461434c0a6961e2b)) * **internal:** fix lint issue ([#1444](https://github.com/openai/openai-python/issues/1444)) ([b0eb458](https://github.com/openai/openai-python/commit/b0eb4582e050b0a25af3d80d2cb584bfc7cd11ab)) ### Documentation * **contributing:** update references to rye-up.com ([dcc34a2](https://github.com/openai/openai-python/commit/dcc34a26d1a6a0debf440724fad658c77547048c)) ## 1.30.2 (2024-05-23) Full Changelog: [v1.30.1...v1.30.2](https://github.com/openai/openai-python/compare/v1.30.1...v1.30.2) ### Chores * **ci:** update rye install location ([#1436](https://github.com/openai/openai-python/issues/1436)) ([f7cc4e7](https://github.com/openai/openai-python/commit/f7cc4e7d5d0964a4a5d53e602379770c2576e1aa)) ## 1.30.1 (2024-05-14) Full Changelog: [v1.30.0...v1.30.1](https://github.com/openai/openai-python/compare/v1.30.0...v1.30.1) ### Chores * **internal:** add slightly better logging to scripts ([#1422](https://github.com/openai/openai-python/issues/1422)) ([43dffab](https://github.com/openai/openai-python/commit/43dffabb3bed4edf8a6e523cbb289f733a5f9b24)) ## 1.30.0 (2024-05-14) Full Changelog: [v1.29.0...v1.30.0](https://github.com/openai/openai-python/compare/v1.29.0...v1.30.0) ### Features * **api:** add incomplete state ([#1420](https://github.com/openai/openai-python/issues/1420)) ([6484984](https://github.com/openai/openai-python/commit/648498412d1c7740e6b67ed4d0a55b89ff29d3b1)) ## 1.29.0 (2024-05-13) Full Changelog: [v1.28.2...v1.29.0](https://github.com/openai/openai-python/compare/v1.28.2...v1.29.0) ### Features * **api:** add gpt-4o model ([#1417](https://github.com/openai/openai-python/issues/1417)) ([4f09f8c](https://github.com/openai/openai-python/commit/4f09f8c6cc4450f5e61f158f1bd54c513063a1a8)) ## 1.28.2 (2024-05-13) Full Changelog: [v1.28.1...v1.28.2](https://github.com/openai/openai-python/compare/v1.28.1...v1.28.2) ### Bug Fixes * **client:** accidental blocking sleep in async code ([#1415](https://github.com/openai/openai-python/issues/1415)) ([0ac6ecb](https://github.com/openai/openai-python/commit/0ac6ecb8d4e52f895bc3ae1f589f22ddaaef6204)) ### Chores * **internal:** bump pydantic dependency ([#1413](https://github.com/openai/openai-python/issues/1413)) ([ed73d1d](https://github.com/openai/openai-python/commit/ed73d1db540714e29a1ba30e3aa6429aae8b1dd8)) ## 1.28.1 (2024-05-11) Full Changelog: [v1.28.0...v1.28.1](https://github.com/openai/openai-python/compare/v1.28.0...v1.28.1) ### Chores * **docs:** add SECURITY.md ([#1408](https://github.com/openai/openai-python/issues/1408)) ([119970a](https://github.com/openai/openai-python/commit/119970a31b67e88c623d50855290ccf3847c10eb)) ## 1.28.0 (2024-05-09) Full Changelog: [v1.27.0...v1.28.0](https://github.com/openai/openai-python/compare/v1.27.0...v1.28.0) ### Features * **api:** add message image content ([#1405](https://github.com/openai/openai-python/issues/1405)) ([a115de6](https://github.com/openai/openai-python/commit/a115de60ce1ca503a7659bb9a19c18699d4d9bcb)) ## 1.27.0 (2024-05-08) Full Changelog: [v1.26.0...v1.27.0](https://github.com/openai/openai-python/compare/v1.26.0...v1.27.0) ### Features * **api:** adding file purposes ([#1401](https://github.com/openai/openai-python/issues/1401)) ([2e9d0bd](https://github.com/openai/openai-python/commit/2e9d0bd0e4bf677ed9b21c6448e804313e026441)) ## 1.26.0 (2024-05-06) Full Changelog: [v1.25.2...v1.26.0](https://github.com/openai/openai-python/compare/v1.25.2...v1.26.0) ### Features * **api:** add usage metadata when streaming ([#1395](https://github.com/openai/openai-python/issues/1395)) ([3cb064b](https://github.com/openai/openai-python/commit/3cb064b10d661dbcc74b6bc1ed7d8e635ab2876a)) ## 1.25.2 (2024-05-05) Full Changelog: [v1.25.1...v1.25.2](https://github.com/openai/openai-python/compare/v1.25.1...v1.25.2) ### Documentation * **readme:** fix misleading timeout example value ([#1393](https://github.com/openai/openai-python/issues/1393)) ([3eba8e7](https://github.com/openai/openai-python/commit/3eba8e7573ec1bf4231a304c8eabc8a8d077f46d)) ## 1.25.1 (2024-05-02) Full Changelog: [v1.25.0...v1.25.1](https://github.com/openai/openai-python/compare/v1.25.0...v1.25.1) ### Chores * **internal:** bump prism version ([#1390](https://github.com/openai/openai-python/issues/1390)) ([a5830fc](https://github.com/openai/openai-python/commit/a5830fc1c5ffd21e2010490905084ad5614212a3)) ## 1.25.0 (2024-05-01) Full Changelog: [v1.24.1...v1.25.0](https://github.com/openai/openai-python/compare/v1.24.1...v1.25.0) ### Features * **api:** delete messages ([#1388](https://github.com/openai/openai-python/issues/1388)) ([d0597cd](https://github.com/openai/openai-python/commit/d0597cdc1813cddffacbaa50565e86d2420d1873)) ## 1.24.1 (2024-04-30) Full Changelog: [v1.24.0...v1.24.1](https://github.com/openai/openai-python/compare/v1.24.0...v1.24.1) ### Chores * **internal:** add link to openapi spec ([#1385](https://github.com/openai/openai-python/issues/1385)) ([b315d04](https://github.com/openai/openai-python/commit/b315d04e9624ec3a841d7c51813bb553640c23ce)) ## 1.24.0 (2024-04-29) Full Changelog: [v1.23.6...v1.24.0](https://github.com/openai/openai-python/compare/v1.23.6...v1.24.0) ### Features * **api:** add required tool_choice ([#1382](https://github.com/openai/openai-python/issues/1382)) ([c558f65](https://github.com/openai/openai-python/commit/c558f651df39f61425cd4109318f78ed94cbf163)) ### Chores * **client:** log response headers in debug mode ([#1383](https://github.com/openai/openai-python/issues/1383)) ([f31a426](https://github.com/openai/openai-python/commit/f31a4261adc4ebd92582cee264e41eb6a6dafc57)) * **internal:** minor reformatting ([#1377](https://github.com/openai/openai-python/issues/1377)) ([7003dbb](https://github.com/openai/openai-python/commit/7003dbb863b6e16381070b8b86ac24aa070a3799)) * **internal:** reformat imports ([#1375](https://github.com/openai/openai-python/issues/1375)) ([2ad0c3b](https://github.com/openai/openai-python/commit/2ad0c3b8e0b746ed20db3c84a9c6a369aa10bf5d)) ## 1.23.6 (2024-04-25) Full Changelog: [v1.23.5...v1.23.6](https://github.com/openai/openai-python/compare/v1.23.5...v1.23.6) ### Chores * **internal:** update test helper function ([#1371](https://github.com/openai/openai-python/issues/1371)) ([6607c4a](https://github.com/openai/openai-python/commit/6607c4a491fd1912f9222d6fe464ccef6e865eac)) ## 1.23.5 (2024-04-24) Full Changelog: [v1.23.4...v1.23.5](https://github.com/openai/openai-python/compare/v1.23.4...v1.23.5) ### Chores * **internal:** use actions/checkout@v4 for codeflow ([#1368](https://github.com/openai/openai-python/issues/1368)) ([d1edf8b](https://github.com/openai/openai-python/commit/d1edf8beb806ebaefdcc2cb6e39f99e1811a2668)) ## 1.23.4 (2024-04-24) Full Changelog: [v1.23.3...v1.23.4](https://github.com/openai/openai-python/compare/v1.23.3...v1.23.4) ### Bug Fixes * **api:** change timestamps to unix integers ([#1367](https://github.com/openai/openai-python/issues/1367)) ([fbc0e15](https://github.com/openai/openai-python/commit/fbc0e15f422971bd15499d4ea5f42a1c885c7004)) * **docs:** doc improvements ([#1364](https://github.com/openai/openai-python/issues/1364)) ([8c3a005](https://github.com/openai/openai-python/commit/8c3a005247ea045b9a95e7459eba2a90067daf71)) ### Chores * **tests:** rename test file ([#1366](https://github.com/openai/openai-python/issues/1366)) ([4204e63](https://github.com/openai/openai-python/commit/4204e63e27584c68ad27825261225603d7a87008)) ## 1.23.3 (2024-04-23) Full Changelog: [v1.23.2...v1.23.3](https://github.com/openai/openai-python/compare/v1.23.2...v1.23.3) ### Chores * **internal:** restructure imports ([#1359](https://github.com/openai/openai-python/issues/1359)) ([4e5eb37](https://github.com/openai/openai-python/commit/4e5eb374ea0545a6117db657bb05f6417bc62d18)) ## 1.23.2 (2024-04-19) Full Changelog: [v1.23.1...v1.23.2](https://github.com/openai/openai-python/compare/v1.23.1...v1.23.2) ### Bug Fixes * **api:** correct types for message attachment tools ([#1348](https://github.com/openai/openai-python/issues/1348)) ([78a6261](https://github.com/openai/openai-python/commit/78a6261eaad7839284903287d4f647d9cb4ced0b)) ## 1.23.1 (2024-04-18) Full Changelog: [v1.23.0...v1.23.1](https://github.com/openai/openai-python/compare/v1.23.0...v1.23.1) ### Bug Fixes * **api:** correct types for attachments ([#1342](https://github.com/openai/openai-python/issues/1342)) ([542d30c](https://github.com/openai/openai-python/commit/542d30c6dad4e139bf3eb443936d42b7b42dad54)) ## 1.23.0 (2024-04-18) Full Changelog: [v1.22.0...v1.23.0](https://github.com/openai/openai-python/compare/v1.22.0...v1.23.0) ### Features * **api:** add request id property to response classes ([#1341](https://github.com/openai/openai-python/issues/1341)) ([444d680](https://github.com/openai/openai-python/commit/444d680cbb3745adbc27788213ae3312567136a8)) ### Documentation * **helpers:** fix example snippets ([#1339](https://github.com/openai/openai-python/issues/1339)) ([8929088](https://github.com/openai/openai-python/commit/8929088b206a04b4c5b85fb69b0b983fb56f9b03)) ## 1.22.0 (2024-04-18) Full Changelog: [v1.21.2...v1.22.0](https://github.com/openai/openai-python/compare/v1.21.2...v1.22.0) ### Features * **api:** batch list endpoint ([#1338](https://github.com/openai/openai-python/issues/1338)) ([a776f38](https://github.com/openai/openai-python/commit/a776f387e3159f9a8f4dcaa7d0d3b78c2a884f91)) ### Chores * **internal:** ban usage of lru_cache ([#1331](https://github.com/openai/openai-python/issues/1331)) ([8f9223b](https://github.com/openai/openai-python/commit/8f9223bfe13200c685fc97c25ada3015a69c6df7)) * **internal:** bump pyright to 1.1.359 ([#1337](https://github.com/openai/openai-python/issues/1337)) ([feec0dd](https://github.com/openai/openai-python/commit/feec0dd1dd243941a279c3224c5ca1d727d76676)) ## 1.21.2 (2024-04-17) Full Changelog: [v1.21.1...v1.21.2](https://github.com/openai/openai-python/compare/v1.21.1...v1.21.2) ### Chores * **internal:** add lru_cache helper function ([#1329](https://github.com/openai/openai-python/issues/1329)) ([cbeebfc](https://github.com/openai/openai-python/commit/cbeebfcca8bf1a3feb4462a79e10099bda5bed84)) ## 1.21.1 (2024-04-17) Full Changelog: [v1.21.0...v1.21.1](https://github.com/openai/openai-python/compare/v1.21.0...v1.21.1) ### Chores * **api:** docs and response_format response property ([#1327](https://github.com/openai/openai-python/issues/1327)) ([7a6d142](https://github.com/openai/openai-python/commit/7a6d142f013994c4eb9a4f55888464c885f8baf0)) ## 1.21.0 (2024-04-17) Full Changelog: [v1.20.0...v1.21.0](https://github.com/openai/openai-python/compare/v1.20.0...v1.21.0) ### Features * **api:** add vector stores ([#1325](https://github.com/openai/openai-python/issues/1325)) ([038a3c5](https://github.com/openai/openai-python/commit/038a3c50db7b6a88f54ff1cd1ff6cbaef2caf87f)) ## 1.20.0 (2024-04-16) Full Changelog: [v1.19.0...v1.20.0](https://github.com/openai/openai-python/compare/v1.19.0...v1.20.0) ### Features * **client:** add header OpenAI-Project ([#1320](https://github.com/openai/openai-python/issues/1320)) ([0c489f1](https://github.com/openai/openai-python/commit/0c489f16a7d9e5ac753da87273b223893edefa69)) * extract chat models to a named enum ([#1322](https://github.com/openai/openai-python/issues/1322)) ([1ccd9b6](https://github.com/openai/openai-python/commit/1ccd9b67322736a4714e58c953d59585322c527d)) ## 1.19.0 (2024-04-15) Full Changelog: [v1.18.0...v1.19.0](https://github.com/openai/openai-python/compare/v1.18.0...v1.19.0) ### Features * **errors:** add request_id property ([#1317](https://github.com/openai/openai-python/issues/1317)) ([f9eb77d](https://github.com/openai/openai-python/commit/f9eb77dca422b9456f4e3b31c7474046235eec1d)) ## 1.18.0 (2024-04-15) Full Changelog: [v1.17.1...v1.18.0](https://github.com/openai/openai-python/compare/v1.17.1...v1.18.0) ### Features * **api:** add batch API ([#1316](https://github.com/openai/openai-python/issues/1316)) ([3e6f19e](https://github.com/openai/openai-python/commit/3e6f19e6e7489bf1c94944a5f8f9b1d4535cdc43)) * **api:** updates ([#1314](https://github.com/openai/openai-python/issues/1314)) ([8281dc9](https://github.com/openai/openai-python/commit/8281dc956178f5de345645660081f7d0c15a57a6)) ## 1.17.1 (2024-04-12) Full Changelog: [v1.17.0...v1.17.1](https://github.com/openai/openai-python/compare/v1.17.0...v1.17.1) ### Chores * fix typo ([#1304](https://github.com/openai/openai-python/issues/1304)) ([1129082](https://github.com/openai/openai-python/commit/1129082955f98d76c0927781ef9e7d0beeda2ec4)) * **internal:** formatting ([#1311](https://github.com/openai/openai-python/issues/1311)) ([8fd411b](https://github.com/openai/openai-python/commit/8fd411b48b6b1eafaab2dac26201525c1ee0b942)) ## 1.17.0 (2024-04-10) Full Changelog: [v1.16.2...v1.17.0](https://github.com/openai/openai-python/compare/v1.16.2...v1.17.0) ### Features * **api:** add additional messages when creating thread run ([#1298](https://github.com/openai/openai-python/issues/1298)) ([70eb081](https://github.com/openai/openai-python/commit/70eb081804b14cc8c151ebd85458545a50a074fd)) * **client:** add DefaultHttpxClient and DefaultAsyncHttpxClient ([#1302](https://github.com/openai/openai-python/issues/1302)) ([69cdfc3](https://github.com/openai/openai-python/commit/69cdfc319fff7ebf28cdd13cc6c1761b7d97811d)) * **models:** add to_dict & to_json helper methods ([#1305](https://github.com/openai/openai-python/issues/1305)) ([40a881d](https://github.com/openai/openai-python/commit/40a881d10442af8b445ce030f8ab338710e1c4c8)) ## 1.16.2 (2024-04-04) Full Changelog: [v1.16.1...v1.16.2](https://github.com/openai/openai-python/compare/v1.16.1...v1.16.2) ### Bug Fixes * **client:** correct logic for line decoding in streaming ([#1293](https://github.com/openai/openai-python/issues/1293)) ([687caef](https://github.com/openai/openai-python/commit/687caefa4acf615bf404f16817bfd9a6f285ee5c)) ## 1.16.1 (2024-04-02) Full Changelog: [v1.16.0...v1.16.1](https://github.com/openai/openai-python/compare/v1.16.0...v1.16.1) ### Chores * **internal:** defer model build for import latency ([#1291](https://github.com/openai/openai-python/issues/1291)) ([bc6866e](https://github.com/openai/openai-python/commit/bc6866eb2335d01532190d0906cad7bf9af28621)) ## 1.16.0 (2024-04-01) Full Changelog: [v1.15.0...v1.16.0](https://github.com/openai/openai-python/compare/v1.15.0...v1.16.0) ### Features * **api:** add support for filtering messages by run_id ([#1288](https://github.com/openai/openai-python/issues/1288)) ([58d6b77](https://github.com/openai/openai-python/commit/58d6b773218ef1dd8dc6208124a16078e4ac11c1)) * **api:** run polling helpers ([#1289](https://github.com/openai/openai-python/issues/1289)) ([6b427f3](https://github.com/openai/openai-python/commit/6b427f38610847bce3ce5334177f07917bd7c187)) ### Chores * **client:** validate that max_retries is not None ([#1286](https://github.com/openai/openai-python/issues/1286)) ([aa5920a](https://github.com/openai/openai-python/commit/aa5920af6131c49a44352524154ee4a1684e76b2)) ### Refactors * rename createAndStream to stream ([6b427f3](https://github.com/openai/openai-python/commit/6b427f38610847bce3ce5334177f07917bd7c187)) ## 1.15.0 (2024-03-31) Full Changelog: [v1.14.3...v1.15.0](https://github.com/openai/openai-python/compare/v1.14.3...v1.15.0) ### Features * **api:** adding temperature parameter ([#1282](https://github.com/openai/openai-python/issues/1282)) ([0e68fd3](https://github.com/openai/openai-python/commit/0e68fd3690155785d1fb0ee9a8604f51e6701b1d)) * **client:** increase default HTTP max_connections to 1000 and max_keepalive_connections to 100 ([#1281](https://github.com/openai/openai-python/issues/1281)) ([340d139](https://github.com/openai/openai-python/commit/340d1391e3071a265ed12c0a8d70d4d73a860bd8)) * **package:** export default constants ([#1275](https://github.com/openai/openai-python/issues/1275)) ([fdc126e](https://github.com/openai/openai-python/commit/fdc126e428320f1bed5eabd3eed229f08ab9effa)) ### Bug Fixes * **project:** use absolute github links on PyPi ([#1280](https://github.com/openai/openai-python/issues/1280)) ([94cd528](https://github.com/openai/openai-python/commit/94cd52837650e5b7e115119d69e6b1c7ba1f6bf1)) ### Chores * **internal:** bump dependencies ([#1273](https://github.com/openai/openai-python/issues/1273)) ([18dcd65](https://github.com/openai/openai-python/commit/18dcd654d9f54628b5fe21a499d1fef500e15f7f)) ### Documentation * **readme:** change undocumented params wording ([#1284](https://github.com/openai/openai-python/issues/1284)) ([7498ef1](https://github.com/openai/openai-python/commit/7498ef1e9568200086ba3efb99ea100feb05e3f0)) ## 1.14.3 (2024-03-25) Full Changelog: [v1.14.2...v1.14.3](https://github.com/openai/openai-python/compare/v1.14.2...v1.14.3) ### Bug Fixes * revert regression with 3.7 support ([#1269](https://github.com/openai/openai-python/issues/1269)) ([37aed56](https://github.com/openai/openai-python/commit/37aed564143dc7281f1eaa6ab64ec5ca334cf25e)) ### Chores * **internal:** construct error properties instead of using the raw response ([#1257](https://github.com/openai/openai-python/issues/1257)) ([11dce5c](https://github.com/openai/openai-python/commit/11dce5c66395722b245f5d5461ce379ca7b939e4)) * **internal:** formatting change ([#1258](https://github.com/openai/openai-python/issues/1258)) ([b907dd7](https://github.com/openai/openai-python/commit/b907dd7dcae895e4209559da061d0991a8d640a6)) * **internal:** loosen input type for util function ([#1250](https://github.com/openai/openai-python/issues/1250)) ([fc8b4c3](https://github.com/openai/openai-python/commit/fc8b4c37dc91dfcc0535c19236092992171784a0)) ### Documentation * **contributing:** fix typo ([#1264](https://github.com/openai/openai-python/issues/1264)) ([835cb9b](https://github.com/openai/openai-python/commit/835cb9b2f92e2aa3329545b4677865dcd4fd00f0)) * **readme:** consistent use of sentence case in headings ([#1255](https://github.com/openai/openai-python/issues/1255)) ([519f371](https://github.com/openai/openai-python/commit/519f371af779b5fa353292ff5a2d3332afe0987e)) * **readme:** document how to make undocumented requests ([#1256](https://github.com/openai/openai-python/issues/1256)) ([5887858](https://github.com/openai/openai-python/commit/5887858a7b649dfde5b733ef01e5cffcf953b2a7)) ## 1.14.2 (2024-03-19) Full Changelog: [v1.14.1...v1.14.2](https://github.com/openai/openai-python/compare/v1.14.1...v1.14.2) ### Performance Improvements * cache TypeAdapters ([#1114](https://github.com/openai/openai-python/issues/1114)) ([41b6fee](https://github.com/openai/openai-python/commit/41b6feec70d3f203e36ba9a92205389bafce930c)) * cache TypeAdapters ([#1243](https://github.com/openai/openai-python/issues/1243)) ([2005076](https://github.com/openai/openai-python/commit/2005076f500bef6e0a6cc8f935b9cc9fef65ab5b)) ### Chores * **internal:** update generated pragma comment ([#1247](https://github.com/openai/openai-python/issues/1247)) ([3eeb9b3](https://github.com/openai/openai-python/commit/3eeb9b3a71e01c2593be443a97a353371466d01a)) ### Documentation * assistant improvements ([#1249](https://github.com/openai/openai-python/issues/1249)) ([e7a3176](https://github.com/openai/openai-python/commit/e7a3176b7606822bd5ad8f7fece87de6aad1e5b6)) * fix typo in CONTRIBUTING.md ([#1245](https://github.com/openai/openai-python/issues/1245)) ([adef57a](https://github.com/openai/openai-python/commit/adef57ae5c71734873ba49bccd92fa7f28068d28)) ## 1.14.1 (2024-03-15) Full Changelog: [v1.14.0...v1.14.1](https://github.com/openai/openai-python/compare/v1.14.0...v1.14.1) ### Documentation * **readme:** assistant streaming ([#1238](https://github.com/openai/openai-python/issues/1238)) ([0fc30a2](https://github.com/openai/openai-python/commit/0fc30a23030b4ff60f27cd2f472517926ed0f300)) ## 1.14.0 (2024-03-13) Full Changelog: [v1.13.4...v1.14.0](https://github.com/openai/openai-python/compare/v1.13.4...v1.14.0) ### Features * **assistants:** add support for streaming ([#1233](https://github.com/openai/openai-python/issues/1233)) ([17635dc](https://github.com/openai/openai-python/commit/17635dccbeddf153f8201dbca18b44e16a1799b2)) ## 1.13.4 (2024-03-13) Full Changelog: [v1.13.3...v1.13.4](https://github.com/openai/openai-python/compare/v1.13.3...v1.13.4) ### Bug Fixes * **streaming:** improve error messages ([#1218](https://github.com/openai/openai-python/issues/1218)) ([4f5ff29](https://github.com/openai/openai-python/commit/4f5ff298601b5a8bfbf0a9d0c0d1329d1502a205)) ### Chores * **api:** update docs ([#1212](https://github.com/openai/openai-python/issues/1212)) ([71236e0](https://github.com/openai/openai-python/commit/71236e0de4012a249af4c1ffd95973a8ba4fa61f)) * **client:** improve error message for invalid http_client argument ([#1216](https://github.com/openai/openai-python/issues/1216)) ([d0c928a](https://github.com/openai/openai-python/commit/d0c928abbd99020fe828350f3adfd10c638a2eed)) * **docs:** mention install from git repo ([#1203](https://github.com/openai/openai-python/issues/1203)) ([3ab6f44](https://github.com/openai/openai-python/commit/3ab6f447ffd8d2394e58416e401e545a99ec85af)) * export NOT_GIVEN sentinel value ([#1223](https://github.com/openai/openai-python/issues/1223)) ([8a4f76f](https://github.com/openai/openai-python/commit/8a4f76f992c66f20cd6aa070c8dc4839e4cf9f3c)) * **internal:** add core support for deserializing into number response ([#1219](https://github.com/openai/openai-python/issues/1219)) ([004bc92](https://github.com/openai/openai-python/commit/004bc924ea579852b9266ca11aea93463cf75104)) * **internal:** bump pyright ([#1221](https://github.com/openai/openai-python/issues/1221)) ([3c2e815](https://github.com/openai/openai-python/commit/3c2e815311ace4ff81ccd446b23ff50a4e099485)) * **internal:** improve deserialisation of discriminated unions ([#1227](https://github.com/openai/openai-python/issues/1227)) ([4767259](https://github.com/openai/openai-python/commit/4767259d25ac135550b37b15e4c0497e5ff0330d)) * **internal:** minor core client restructuring ([#1199](https://github.com/openai/openai-python/issues/1199)) ([4314cdc](https://github.com/openai/openai-python/commit/4314cdcd522537e6cbbd87206d5bb236f672ce05)) * **internal:** split up transforms into sync / async ([#1210](https://github.com/openai/openai-python/issues/1210)) ([7853a83](https://github.com/openai/openai-python/commit/7853a8358864957cc183581bdf7c03810a7b2756)) * **internal:** support more input types ([#1211](https://github.com/openai/openai-python/issues/1211)) ([d0e4baa](https://github.com/openai/openai-python/commit/d0e4baa40d32c2da0ce5ceef8e0c7193b98f2b5a)) * **internal:** support parsing Annotated types ([#1222](https://github.com/openai/openai-python/issues/1222)) ([8598f81](https://github.com/openai/openai-python/commit/8598f81841eeab0ab00eb21fdec7e8756ffde909)) * **types:** include discriminators in unions ([#1228](https://github.com/openai/openai-python/issues/1228)) ([3ba0dcc](https://github.com/openai/openai-python/commit/3ba0dcc19a2af0ef869c77da2805278f71ee96c2)) ### Documentation * **contributing:** improve wording ([#1201](https://github.com/openai/openai-python/issues/1201)) ([95a1e0e](https://github.com/openai/openai-python/commit/95a1e0ea8e5446c413606847ebf9e35afbc62bf9)) ## 1.13.3 (2024-02-28) Full Changelog: [v1.13.2...v1.13.3](https://github.com/openai/openai-python/compare/v1.13.2...v1.13.3) ### Features * **api:** add wav and pcm to response_format ([#1189](https://github.com/openai/openai-python/issues/1189)) ([dbd20fc](https://github.com/openai/openai-python/commit/dbd20fc42e93358261f71b9aa0e5f955053c3825)) ### Chores * **client:** use anyio.sleep instead of asyncio.sleep ([#1198](https://github.com/openai/openai-python/issues/1198)) ([b6d025b](https://github.com/openai/openai-python/commit/b6d025b54f091e79f5d4a0a8923f29574fd66027)) * **internal:** bump pyright ([#1193](https://github.com/openai/openai-python/issues/1193)) ([9202e04](https://github.com/openai/openai-python/commit/9202e04d07a7c47232f39196346c734869b8f55a)) * **types:** extract run status to a named type ([#1178](https://github.com/openai/openai-python/issues/1178)) ([249ecbd](https://github.com/openai/openai-python/commit/249ecbdeb6566a385ec46dfd5000b4eaa03965f0)) ### Documentation * add note in azure_deployment docstring ([#1188](https://github.com/openai/openai-python/issues/1188)) ([96fa995](https://github.com/openai/openai-python/commit/96fa99572dd76ee708f2bae04d11b659cdd698b2)) * **examples:** add pyaudio streaming example ([#1194](https://github.com/openai/openai-python/issues/1194)) ([3683c5e](https://github.com/openai/openai-python/commit/3683c5e3c7f07e4b789a0c4cc417b2c59539cae2)) ## 1.13.2 (2024-02-20) Full Changelog: [v1.13.1...v1.13.2](https://github.com/openai/openai-python/compare/v1.13.1...v1.13.2) ### Bug Fixes * **ci:** revert "move github release logic to github app" ([#1170](https://github.com/openai/openai-python/issues/1170)) ([f1adc2e](https://github.com/openai/openai-python/commit/f1adc2e6f2f29acb4404e84137a9d3109714c585)) ## 1.13.1 (2024-02-20) Full Changelog: [v1.13.0...v1.13.1](https://github.com/openai/openai-python/compare/v1.13.0...v1.13.1) ### Chores * **internal:** bump rye to v0.24.0 ([#1168](https://github.com/openai/openai-python/issues/1168)) ([84c4256](https://github.com/openai/openai-python/commit/84c4256316f2a79068ecadb852e5e69b6b104a1f)) ## 1.13.0 (2024-02-19) Full Changelog: [v1.12.0...v1.13.0](https://github.com/openai/openai-python/compare/v1.12.0...v1.13.0) ### Features * **api:** updates ([#1146](https://github.com/openai/openai-python/issues/1146)) ([79b7675](https://github.com/openai/openai-python/commit/79b7675e51fb7d269a6ea281a568bc7812ba2ace)) ### Bug Fixes * **api:** remove non-GA instance_id param ([#1164](https://github.com/openai/openai-python/issues/1164)) ([1abe139](https://github.com/openai/openai-python/commit/1abe139b1a5f5cc41263738fc12856056dce5697)) ### Chores * **ci:** move github release logic to github app ([#1155](https://github.com/openai/openai-python/issues/1155)) ([67cfac2](https://github.com/openai/openai-python/commit/67cfac2564dfb718da0465e34b90ac6928fa962a)) * **client:** use correct accept headers for binary data ([#1161](https://github.com/openai/openai-python/issues/1161)) ([e536437](https://github.com/openai/openai-python/commit/e536437ae0b2cb0ddf2d74618722005d37403f32)) * **internal:** refactor release environment script ([#1158](https://github.com/openai/openai-python/issues/1158)) ([7fe8ec3](https://github.com/openai/openai-python/commit/7fe8ec3bf04ecf85e3bd5adf0d9992c051f87b81)) ## 1.12.0 (2024-02-08) Full Changelog: [v1.11.1...v1.12.0](https://github.com/openai/openai-python/compare/v1.11.1...v1.12.0) ### Features * **api:** add `timestamp_granularities`, add `gpt-3.5-turbo-0125` model ([#1125](https://github.com/openai/openai-python/issues/1125)) ([1ecf8f6](https://github.com/openai/openai-python/commit/1ecf8f6b12323ed09fb6a2815c85b9533ee52a50)) * **cli/images:** add support for `--model` arg ([#1132](https://github.com/openai/openai-python/issues/1132)) ([0d53866](https://github.com/openai/openai-python/commit/0d5386615cda7cd50d5db90de2119b84dba29519)) ### Bug Fixes * remove double brackets from timestamp_granularities param ([#1140](https://github.com/openai/openai-python/issues/1140)) ([3db0222](https://github.com/openai/openai-python/commit/3db022216a81fa86470b53ec1246669bc7b17897)) * **types:** loosen most List params types to Iterable ([#1129](https://github.com/openai/openai-python/issues/1129)) ([bdb31a3](https://github.com/openai/openai-python/commit/bdb31a3b1db6ede4e02b3c951c4fd23f70260038)) ### Chores * **internal:** add lint command ([#1128](https://github.com/openai/openai-python/issues/1128)) ([4c021c0](https://github.com/openai/openai-python/commit/4c021c0ab0151c2ec092d860c9b60e22e658cd03)) * **internal:** support serialising iterable types ([#1127](https://github.com/openai/openai-python/issues/1127)) ([98d4e59](https://github.com/openai/openai-python/commit/98d4e59afcf2d65d4e660d91eb9462240ef5cd63)) ### Documentation * add CONTRIBUTING.md ([#1138](https://github.com/openai/openai-python/issues/1138)) ([79c8f0e](https://github.com/openai/openai-python/commit/79c8f0e8bf5470e2e31e781e8d279331e89ddfbe)) ## 1.11.1 (2024-02-04) Full Changelog: [v1.11.0...v1.11.1](https://github.com/openai/openai-python/compare/v1.11.0...v1.11.1) ### Bug Fixes * prevent crash when platform.architecture() is not allowed ([#1120](https://github.com/openai/openai-python/issues/1120)) ([9490554](https://github.com/openai/openai-python/commit/949055488488e93597cbc6c2cdd81f14f203e53b)) ## 1.11.0 (2024-02-03) Full Changelog: [v1.10.0...v1.11.0](https://github.com/openai/openai-python/compare/v1.10.0...v1.11.0) ### Features * **client:** support parsing custom response types ([#1111](https://github.com/openai/openai-python/issues/1111)) ([da00fc3](https://github.com/openai/openai-python/commit/da00fc3f8e0ff13c6c3ca970e4bb86846304bd06)) ### Chores * **interal:** make link to api.md relative ([#1117](https://github.com/openai/openai-python/issues/1117)) ([4a10879](https://github.com/openai/openai-python/commit/4a108797e46293357601ce933e21b557a5dc6954)) * **internal:** cast type in mocked test ([#1112](https://github.com/openai/openai-python/issues/1112)) ([99b21e1](https://github.com/openai/openai-python/commit/99b21e1fc681eb10e01d479cc043ad3c89272b1c)) * **internal:** enable ruff type checking misuse lint rule ([#1106](https://github.com/openai/openai-python/issues/1106)) ([fa63e60](https://github.com/openai/openai-python/commit/fa63e605c82ec78f4fc27469c434b421a08fb909)) * **internal:** support multipart data with overlapping keys ([#1104](https://github.com/openai/openai-python/issues/1104)) ([455bc9f](https://github.com/openai/openai-python/commit/455bc9f1fd018a32cd604eb4b400e05aa8d71822)) * **internal:** support pre-release versioning ([#1113](https://github.com/openai/openai-python/issues/1113)) ([dea5b08](https://github.com/openai/openai-python/commit/dea5b08c28d47b331fd44f6920cf9fe322b68e51)) ## 1.10.0 (2024-01-25) Full Changelog: [v1.9.0...v1.10.0](https://github.com/openai/openai-python/compare/v1.9.0...v1.10.0) ### Features * **api:** add text embeddings dimensions param ([#1103](https://github.com/openai/openai-python/issues/1103)) ([94abfa0](https://github.com/openai/openai-python/commit/94abfa0f988c199ea95a9c870c4ae9808823186d)) * **azure:** proactively add audio/speech to deployment endpoints ([#1099](https://github.com/openai/openai-python/issues/1099)) ([fdf8742](https://github.com/openai/openai-python/commit/fdf87429b45ceb47ae6fd068ab70cc07bcb8da44)) * **client:** enable follow redirects by default ([#1100](https://github.com/openai/openai-python/issues/1100)) ([d325b7c](https://github.com/openai/openai-python/commit/d325b7ca594c2abaada536249b5633b106943333)) ### Chores * **internal:** add internal helpers ([#1092](https://github.com/openai/openai-python/issues/1092)) ([629bde5](https://github.com/openai/openai-python/commit/629bde5800d84735e22d924db23109a141f48644)) ### Refactors * remove unnecessary builtin import ([#1094](https://github.com/openai/openai-python/issues/1094)) ([504b7d4](https://github.com/openai/openai-python/commit/504b7d4a0b4715bd49a1a076a8d4868e51fb3351)) ## 1.9.0 (2024-01-21) Full Changelog: [v1.8.0...v1.9.0](https://github.com/openai/openai-python/compare/v1.8.0...v1.9.0) ### Features * **api:** add usage to runs and run steps ([#1090](https://github.com/openai/openai-python/issues/1090)) ([6c116df](https://github.com/openai/openai-python/commit/6c116dfbb0065d15050450df70e0e98fc8c80349)) ### Chores * **internal:** fix typing util function ([#1083](https://github.com/openai/openai-python/issues/1083)) ([3e60db6](https://github.com/openai/openai-python/commit/3e60db69f5d9187c4eb38451967259f534a36a82)) * **internal:** remove redundant client test ([#1085](https://github.com/openai/openai-python/issues/1085)) ([947974f](https://github.com/openai/openai-python/commit/947974f5af726e252b7b12c863743e50f41b79d3)) * **internal:** share client instances between all tests ([#1088](https://github.com/openai/openai-python/issues/1088)) ([05cd753](https://github.com/openai/openai-python/commit/05cd7531d40774d05c52b14dee54d137ac1452a3)) * **internal:** speculative retry-after-ms support ([#1086](https://github.com/openai/openai-python/issues/1086)) ([36a7576](https://github.com/openai/openai-python/commit/36a7576a913be8509a3cf6f262543083b485136e)) * lazy load raw resource class properties ([#1087](https://github.com/openai/openai-python/issues/1087)) ([d307127](https://github.com/openai/openai-python/commit/d30712744be07461e86763705c03c3495eadfc35)) ## 1.8.0 (2024-01-16) Full Changelog: [v1.7.2...v1.8.0](https://github.com/openai/openai-python/compare/v1.7.2...v1.8.0) ### Features * **client:** add support for streaming raw responses ([#1072](https://github.com/openai/openai-python/issues/1072)) ([0e93c3b](https://github.com/openai/openai-python/commit/0e93c3b5bc9cfa041e91962fd82c0d9358125024)) ### Bug Fixes * **client:** ensure path params are non-empty ([#1075](https://github.com/openai/openai-python/issues/1075)) ([9a25149](https://github.com/openai/openai-python/commit/9a2514997c2ddccbec9df8be3773e83271f1dab8)) * **proxy:** prevent recursion errors when debugging pycharm ([#1076](https://github.com/openai/openai-python/issues/1076)) ([3d78798](https://github.com/openai/openai-python/commit/3d787987cf7625b5b502cb0b63a37d55956eaf1d)) ### Chores * add write_to_file binary helper method ([#1077](https://github.com/openai/openai-python/issues/1077)) ([c622c6a](https://github.com/openai/openai-python/commit/c622c6aaf2ae7dc62bd6cdfc053204c5dc3293ac)) ## 1.7.2 (2024-01-12) Full Changelog: [v1.7.1...v1.7.2](https://github.com/openai/openai-python/compare/v1.7.1...v1.7.2) ### Documentation * **readme:** improve api reference ([#1065](https://github.com/openai/openai-python/issues/1065)) ([745b9e0](https://github.com/openai/openai-python/commit/745b9e08ae0abb8bf4cd87ed40fa450d9ad81ede)) ### Refactors * **api:** remove deprecated endpoints ([#1067](https://github.com/openai/openai-python/issues/1067)) ([199ddcd](https://github.com/openai/openai-python/commit/199ddcdca00c136e4e0c3ff16521eff22acf2a1a)) ## 1.7.1 (2024-01-10) Full Changelog: [v1.7.0...v1.7.1](https://github.com/openai/openai-python/compare/v1.7.0...v1.7.1) ### Chores * **client:** improve debug logging for failed requests ([#1060](https://github.com/openai/openai-python/issues/1060)) ([cf9a651](https://github.com/openai/openai-python/commit/cf9a6517b4aa0f24bcbe143c54ea908d43dfda92)) ## 1.7.0 (2024-01-08) Full Changelog: [v1.6.1...v1.7.0](https://github.com/openai/openai-python/compare/v1.6.1...v1.7.0) ### Features * add `None` default value to nullable response properties ([#1043](https://github.com/openai/openai-python/issues/1043)) ([d94b4d3](https://github.com/openai/openai-python/commit/d94b4d3d0adcd1a49a1c25cc9730cef013a3e9c9)) ### Bug Fixes * **client:** correctly use custom http client auth ([#1028](https://github.com/openai/openai-python/issues/1028)) ([3d7d93e](https://github.com/openai/openai-python/commit/3d7d93e951eb7fe09cd9d94d10a62a020398c7f9)) ### Chores * add .keep files for examples and custom code directories ([#1057](https://github.com/openai/openai-python/issues/1057)) ([7524097](https://github.com/openai/openai-python/commit/7524097a47af0fdc8b560186ef3b111b59430741)) * **internal:** bump license ([#1037](https://github.com/openai/openai-python/issues/1037)) ([d828527](https://github.com/openai/openai-python/commit/d828527540ebd97679075f48744818f06311b0cb)) * **internal:** loosen type var restrictions ([#1049](https://github.com/openai/openai-python/issues/1049)) ([e00876b](https://github.com/openai/openai-python/commit/e00876b20b93038450eb317899d8775c7661b8eb)) * **internal:** replace isort with ruff ([#1042](https://github.com/openai/openai-python/issues/1042)) ([f1fbc9c](https://github.com/openai/openai-python/commit/f1fbc9c0d62e7d89ab32c8bdfa39cd94b560690b)) * **internal:** update formatting ([#1041](https://github.com/openai/openai-python/issues/1041)) ([2e9ecee](https://github.com/openai/openai-python/commit/2e9ecee9bdfa8ec33b1b1527d5187483b700fad3)) * **src:** fix typos ([#988](https://github.com/openai/openai-python/issues/988)) ([6a8b806](https://github.com/openai/openai-python/commit/6a8b80624636f9a0e5ada151b2509710a6f74808)) * use property declarations for resource members ([#1047](https://github.com/openai/openai-python/issues/1047)) ([131f6bc](https://github.com/openai/openai-python/commit/131f6bc6b0ccf79119096057079e10906b3d4678)) ### Documentation * fix docstring typos ([#1022](https://github.com/openai/openai-python/issues/1022)) ([ad3fd2c](https://github.com/openai/openai-python/commit/ad3fd2cd19bf91f94473e368554dff39a8f9ad16)) * improve audio example to show how to stream to a file ([#1017](https://github.com/openai/openai-python/issues/1017)) ([d45ed7f](https://github.com/openai/openai-python/commit/d45ed7f0513b167555ae875f1877fa205c5790d2)) ## 1.6.1 (2023-12-22) Full Changelog: [v1.6.0...v1.6.1](https://github.com/openai/openai-python/compare/v1.6.0...v1.6.1) ### Chores * **internal:** add bin script ([#1001](https://github.com/openai/openai-python/issues/1001)) ([99ffbda](https://github.com/openai/openai-python/commit/99ffbda279bf4c159511fb96b1d5bb688af25437)) * **internal:** use ruff instead of black for formatting ([#1008](https://github.com/openai/openai-python/issues/1008)) ([ceaf9a0](https://github.com/openai/openai-python/commit/ceaf9a06fbd1a846756bb72cce50a69c8cc20bd3)) ## 1.6.0 (2023-12-19) Full Changelog: [v1.5.0...v1.6.0](https://github.com/openai/openai-python/compare/v1.5.0...v1.6.0) ### Features * **api:** add additional instructions for runs ([#995](https://github.com/openai/openai-python/issues/995)) ([7bf9b75](https://github.com/openai/openai-python/commit/7bf9b75067905449e83e828c12eb384022cff6ca)) ### Chores * **cli:** fix typo in completions ([#985](https://github.com/openai/openai-python/issues/985)) ([d1e9e8f](https://github.com/openai/openai-python/commit/d1e9e8f24df366bb7b796c55a98247c025d229f5)) * **cli:** fix typo in completions ([#986](https://github.com/openai/openai-python/issues/986)) ([626bc34](https://github.com/openai/openai-python/commit/626bc34d82a7057bac99f8b556f9e5f60c261ee7)) * **internal:** fix binary response tests ([#983](https://github.com/openai/openai-python/issues/983)) ([cfb7e30](https://github.com/openai/openai-python/commit/cfb7e308393f2e912e959dd10d68096dd5b3ab9c)) * **internal:** fix typos ([#993](https://github.com/openai/openai-python/issues/993)) ([3b338a4](https://github.com/openai/openai-python/commit/3b338a401b206618774291ff8137deb0cc5f6b4c)) * **internal:** minor utils restructuring ([#992](https://github.com/openai/openai-python/issues/992)) ([5ba576a](https://github.com/openai/openai-python/commit/5ba576ae38d2c4c4d32a21933e0d68e0bc2f0d49)) * **package:** bump minimum typing-extensions to 4.7 ([#994](https://github.com/openai/openai-python/issues/994)) ([0c2da84](https://github.com/openai/openai-python/commit/0c2da84badf416f8b2213983f68bd2b6f9e52f2b)) * **streaming:** update constructor to use direct client names ([#991](https://github.com/openai/openai-python/issues/991)) ([6c3427d](https://github.com/openai/openai-python/commit/6c3427dac8c414658516aeb4caf5d5fd8b11097b)) ### Documentation * upgrade models in examples to latest version ([#989](https://github.com/openai/openai-python/issues/989)) ([cedd574](https://github.com/openai/openai-python/commit/cedd574e5611f3e71e92b523a72ba87bcfe546f1)) ## 1.5.0 (2023-12-17) Full Changelog: [v1.4.0...v1.5.0](https://github.com/openai/openai-python/compare/v1.4.0...v1.5.0) ### Features * **api:** add token logprobs to chat completions ([#980](https://github.com/openai/openai-python/issues/980)) ([f50e962](https://github.com/openai/openai-python/commit/f50e962b930bd682a4299143b2995337e8571273)) ### Chores * **ci:** run release workflow once per day ([#978](https://github.com/openai/openai-python/issues/978)) ([215476a](https://github.com/openai/openai-python/commit/215476a0b99e0c92ab3e44ddd25de207af32d160)) ## 1.4.0 (2023-12-15) Full Changelog: [v1.3.9...v1.4.0](https://github.com/openai/openai-python/compare/v1.3.9...v1.4.0) ### Features * **api:** add optional `name` argument + improve docs ([#972](https://github.com/openai/openai-python/issues/972)) ([7972010](https://github.com/openai/openai-python/commit/7972010615820099f662c02821cfbd59e7d6ea44)) ## 1.3.9 (2023-12-12) Full Changelog: [v1.3.8...v1.3.9](https://github.com/openai/openai-python/compare/v1.3.8...v1.3.9) ### Documentation * improve README timeout comment ([#964](https://github.com/openai/openai-python/issues/964)) ([3c3ed5e](https://github.com/openai/openai-python/commit/3c3ed5edd938a9333e8d2fa47cb4b44178eef89a)) * small Improvement in the async chat response code ([#959](https://github.com/openai/openai-python/issues/959)) ([fb9d0a3](https://github.com/openai/openai-python/commit/fb9d0a358fa232043d9d5c149b6a888d50127c7b)) * small streaming readme improvements ([#962](https://github.com/openai/openai-python/issues/962)) ([f3be2e5](https://github.com/openai/openai-python/commit/f3be2e5cc24988471e6cedb3e34bdfd3123edc63)) ### Refactors * **client:** simplify cleanup ([#966](https://github.com/openai/openai-python/issues/966)) ([5c138f4](https://github.com/openai/openai-python/commit/5c138f4a7947e5b4aae8779fae78ca51269b355a)) * simplify internal error handling ([#968](https://github.com/openai/openai-python/issues/968)) ([d187f6b](https://github.com/openai/openai-python/commit/d187f6b6e4e646cca39c6ca35c618aa5c1bfbd61)) ## 1.3.8 (2023-12-08) Full Changelog: [v1.3.7...v1.3.8](https://github.com/openai/openai-python/compare/v1.3.7...v1.3.8) ### Bug Fixes * avoid leaking memory when Client.with_options is used ([#956](https://github.com/openai/openai-python/issues/956)) ([e37ecca](https://github.com/openai/openai-python/commit/e37ecca04040ce946822a7e40f5604532a59ee85)) * **errors:** properly assign APIError.body ([#949](https://github.com/openai/openai-python/issues/949)) ([c70e194](https://github.com/openai/openai-python/commit/c70e194f0a253409ec851607ae5219e3b5a8c442)) * **pagination:** use correct type hint for .object ([#943](https://github.com/openai/openai-python/issues/943)) ([23fe7ee](https://github.com/openai/openai-python/commit/23fe7ee48a71539b0d1e95ceff349264aae4090e)) ### Chores * **internal:** enable more lint rules ([#945](https://github.com/openai/openai-python/issues/945)) ([2c8add6](https://github.com/openai/openai-python/commit/2c8add64a261dea731bd162bb0cca222518d5440)) * **internal:** reformat imports ([#939](https://github.com/openai/openai-python/issues/939)) ([ec65124](https://github.com/openai/openai-python/commit/ec651249de2f4e4cf959f816e1b52f03d3b1017a)) * **internal:** reformat imports ([#944](https://github.com/openai/openai-python/issues/944)) ([5290639](https://github.com/openai/openai-python/commit/52906391c9b6633656ec7934e6bbac553ec667cd)) * **internal:** update formatting ([#941](https://github.com/openai/openai-python/issues/941)) ([8e5a156](https://github.com/openai/openai-python/commit/8e5a156d555fe68731ba0604a7455cc03cb451ce)) * **package:** lift anyio v4 restriction ([#927](https://github.com/openai/openai-python/issues/927)) ([be0438a](https://github.com/openai/openai-python/commit/be0438a2e399bb0e0a94907229d02fc61ab479c0)) ### Documentation * fix typo in example ([#950](https://github.com/openai/openai-python/issues/950)) ([54f0ce0](https://github.com/openai/openai-python/commit/54f0ce0000abe32e97ae400f2975c028b8a84273)) ## 1.3.7 (2023-12-01) Full Changelog: [v1.3.6...v1.3.7](https://github.com/openai/openai-python/compare/v1.3.6...v1.3.7) ### Bug Fixes * **client:** correct base_url setter implementation ([#919](https://github.com/openai/openai-python/issues/919)) ([135d9cf](https://github.com/openai/openai-python/commit/135d9cf2820f1524764bf536a9322830bdcd5875)) * **client:** don't cause crashes when inspecting the module ([#897](https://github.com/openai/openai-python/issues/897)) ([db029a5](https://github.com/openai/openai-python/commit/db029a596c90b1af4ef0bfb1cdf31f54b2f5755d)) * **client:** ensure retried requests are closed ([#902](https://github.com/openai/openai-python/issues/902)) ([e025e6b](https://github.com/openai/openai-python/commit/e025e6bee44ea145d948869ef0c79bac0c376b9f)) ### Chores * **internal:** add tests for proxy change ([#899](https://github.com/openai/openai-python/issues/899)) ([71a13d0](https://github.com/openai/openai-python/commit/71a13d0c70d105b2b97720c72a1003b942cda2ae)) * **internal:** remove unused type var ([#915](https://github.com/openai/openai-python/issues/915)) ([4233bcd](https://github.com/openai/openai-python/commit/4233bcdae5f467f10454fcc008a6e728fa846830)) * **internal:** replace string concatenation with f-strings ([#908](https://github.com/openai/openai-python/issues/908)) ([663a8f6](https://github.com/openai/openai-python/commit/663a8f6dead5aa523d1e8779e75af1dabb1690c4)) * **internal:** replace string concatenation with f-strings ([#909](https://github.com/openai/openai-python/issues/909)) ([caab767](https://github.com/openai/openai-python/commit/caab767156375114078cf8d85031863361326b5f)) ### Documentation * fix typo in readme ([#904](https://github.com/openai/openai-python/issues/904)) ([472cd44](https://github.com/openai/openai-python/commit/472cd44e45a45b0b4f12583a5402e8aeb121d7a2)) * **readme:** update example snippets ([#907](https://github.com/openai/openai-python/issues/907)) ([bbb648e](https://github.com/openai/openai-python/commit/bbb648ef81eb11f81b457e2cbf33a832f4d29a76)) ## 1.3.6 (2023-11-28) Full Changelog: [v1.3.5...v1.3.6](https://github.com/openai/openai-python/compare/v1.3.5...v1.3.6) ### Bug Fixes * **client:** add support for streaming binary responses ([#866](https://github.com/openai/openai-python/issues/866)) ([2470d25](https://github.com/openai/openai-python/commit/2470d251b751e92e8950bc9e3026965e9925ac1c)) ### Chores * **deps:** bump mypy to v1.7.1 ([#891](https://github.com/openai/openai-python/issues/891)) ([11fcb2a](https://github.com/openai/openai-python/commit/11fcb2a3cd4205b307c13c65ad47d9e315b0084d)) * **internal:** send more detailed x-stainless headers ([#877](https://github.com/openai/openai-python/issues/877)) ([69e0549](https://github.com/openai/openai-python/commit/69e054947d587ff2548b101ece690d21d3c38f74)) * revert binary streaming change ([#875](https://github.com/openai/openai-python/issues/875)) ([0a06d6a](https://github.com/openai/openai-python/commit/0a06d6a078c5ee898dae75bab4988e1a1936bfbf)) ### Documentation * **readme:** minor updates ([#894](https://github.com/openai/openai-python/issues/894)) ([5458457](https://github.com/openai/openai-python/commit/54584572df4c2a086172d812c6acb84e3405328b)) * **readme:** update examples ([#893](https://github.com/openai/openai-python/issues/893)) ([124da87](https://github.com/openai/openai-python/commit/124da8720c44d40c083d29179f46a265761c1f4f)) * update readme code snippet ([#890](https://github.com/openai/openai-python/issues/890)) ([c522f21](https://github.com/openai/openai-python/commit/c522f21e2a685454185d57e462e74a28499460f9)) ## 1.3.5 (2023-11-21) Full Changelog: [v1.3.4...v1.3.5](https://github.com/openai/openai-python/compare/v1.3.4...v1.3.5) ### Bug Fixes * **azure:** ensure custom options can be passed to copy ([#858](https://github.com/openai/openai-python/issues/858)) ([05ca0d6](https://github.com/openai/openai-python/commit/05ca0d68e84d40f975614d27cb52c0f382104377)) ### Chores * **package:** add license classifier ([#826](https://github.com/openai/openai-python/issues/826)) ([bec004d](https://github.com/openai/openai-python/commit/bec004d030b277e05bdd51f66fae1e881291c30b)) * **package:** add license classifier metadata ([#860](https://github.com/openai/openai-python/issues/860)) ([80dffb1](https://github.com/openai/openai-python/commit/80dffb17ff0a10b0b9ea704c4247521e48b68408)) ## 1.3.4 (2023-11-21) Full Changelog: [v1.3.3...v1.3.4](https://github.com/openai/openai-python/compare/v1.3.3...v1.3.4) ### Bug Fixes * **client:** attempt to parse unknown json content types ([#854](https://github.com/openai/openai-python/issues/854)) ([ba50466](https://github.com/openai/openai-python/commit/ba5046611029a67714d5120b9cc6a3c7fecce10c)) ### Chores * **examples:** fix static types in assistants example ([#852](https://github.com/openai/openai-python/issues/852)) ([5b47b2c](https://github.com/openai/openai-python/commit/5b47b2c542b9b4fb143af121022e2d5ad0890ef4)) ## 1.3.3 (2023-11-17) Full Changelog: [v1.3.2...v1.3.3](https://github.com/openai/openai-python/compare/v1.3.2...v1.3.3) ### Chores * **internal:** update type hint for helper function ([#846](https://github.com/openai/openai-python/issues/846)) ([9a5966c](https://github.com/openai/openai-python/commit/9a5966c70fce620a183de580938556730564a405)) ## 1.3.2 (2023-11-16) Full Changelog: [v1.3.1...v1.3.2](https://github.com/openai/openai-python/compare/v1.3.1...v1.3.2) ### Documentation * **readme:** minor updates ([#841](https://github.com/openai/openai-python/issues/841)) ([7273ad1](https://github.com/openai/openai-python/commit/7273ad1510043d3e264969c72403a1a237401910)) ## 1.3.1 (2023-11-16) Full Changelog: [v1.3.0...v1.3.1](https://github.com/openai/openai-python/compare/v1.3.0...v1.3.1) ### Chores * **internal:** add publish script ([#838](https://github.com/openai/openai-python/issues/838)) ([3ea41bc](https://github.com/openai/openai-python/commit/3ea41bcede374c4e5c92d85108281637c3382e12)) ## 1.3.0 (2023-11-15) Full Changelog: [v1.2.4...v1.3.0](https://github.com/openai/openai-python/compare/v1.2.4...v1.3.0) ### Features * **api:** add gpt-3.5-turbo-1106 ([#813](https://github.com/openai/openai-python/issues/813)) ([9bb3c4e](https://github.com/openai/openai-python/commit/9bb3c4ed88c890db2605a793aa39fffa1d84e8ef)) * **client:** support reading the base url from an env variable ([#829](https://github.com/openai/openai-python/issues/829)) ([ca5fdc6](https://github.com/openai/openai-python/commit/ca5fdc6ca006a3550cc5eeea70dd3d96b9ba305a)) ### Bug Fixes * **breaking!:** correct broken type names in moderation categories ([#811](https://github.com/openai/openai-python/issues/811)) ([0bc211f](https://github.com/openai/openai-python/commit/0bc211fd46f4fcc1f7687bdfdce26894b679cb4f)) ### Chores * fix typo in docs and add request header for function calls ([#807](https://github.com/openai/openai-python/issues/807)) ([cbef703](https://github.com/openai/openai-python/commit/cbef7030c7b21a0c766fe83c62657cea1cd8d31c)) * **internal:** fix devcontainer interpeter path ([#810](https://github.com/openai/openai-python/issues/810)) ([0acc07d](https://github.com/openai/openai-python/commit/0acc07dd8281ba881f91689b8a5e4254e8743fbc)) ### Documentation * add azure env vars ([#814](https://github.com/openai/openai-python/issues/814)) ([bd8e32a](https://github.com/openai/openai-python/commit/bd8e32a380218d0c9ff43643ccc1a25b3c35120d)) * fix code comment typo ([#790](https://github.com/openai/openai-python/issues/790)) ([8407a27](https://github.com/openai/openai-python/commit/8407a27e848ae611eb087c8d10632447d7c55498)) * **readme:** fix broken azure_ad notebook link ([#781](https://github.com/openai/openai-python/issues/781)) ([3b92cdf](https://github.com/openai/openai-python/commit/3b92cdfa5490b50a72811bec2f6e54e070847961)) ## 1.2.4 (2023-11-13) Full Changelog: [v1.2.3...v1.2.4](https://github.com/openai/openai-python/compare/v1.2.3...v1.2.4) ### Bug Fixes * **client:** retry if SSLWantReadError occurs in the async client ([#804](https://github.com/openai/openai-python/issues/804)) ([be82288](https://github.com/openai/openai-python/commit/be82288f3c88c10c9ac20ba3b8cb53b5c7a4e2f9)) ## 1.2.3 (2023-11-10) Full Changelog: [v1.2.2...v1.2.3](https://github.com/openai/openai-python/compare/v1.2.2...v1.2.3) ### Bug Fixes * **cli/audio:** file format detection failing for whisper ([#733](https://github.com/openai/openai-python/issues/733)) ([01079d6](https://github.com/openai/openai-python/commit/01079d6dca13e0ec158dff81e0706d8a9d6c02ef)) * **client:** correctly flush the stream response body ([#771](https://github.com/openai/openai-python/issues/771)) ([0d52731](https://github.com/openai/openai-python/commit/0d5273165c96286f8456ae04b9eb0de5144e52f8)) * **client:** serialise pydantic v1 default fields correctly in params ([#776](https://github.com/openai/openai-python/issues/776)) ([d4c49ad](https://github.com/openai/openai-python/commit/d4c49ad2be9c0d926eece5fd33f6836279ea21e2)) * **models:** mark unknown fields as set in pydantic v1 ([#772](https://github.com/openai/openai-python/issues/772)) ([ae032a1](https://github.com/openai/openai-python/commit/ae032a1ba4efa72284a572bfaf0305af50142835)) * prevent IndexError in fine-tunes CLI ([#768](https://github.com/openai/openai-python/issues/768)) ([42f1633](https://github.com/openai/openai-python/commit/42f16332cf0f96f243f9797d6406283865254355)) ### Documentation * reword package description ([#764](https://github.com/openai/openai-python/issues/764)) ([9ff10df](https://github.com/openai/openai-python/commit/9ff10df30ca2d44978eb5f982ccf039c9f1bf1bf)) ## 1.2.2 (2023-11-09) Full Changelog: [v1.2.1...v1.2.2](https://github.com/openai/openai-python/compare/v1.2.1...v1.2.2) ### Bug Fixes * **client:** correctly assign error properties ([#759](https://github.com/openai/openai-python/issues/759)) ([ef264d2](https://github.com/openai/openai-python/commit/ef264d2293b77784f69039291ca2a17a454851cb)) ### Documentation * **readme:** link to migration guide ([#761](https://github.com/openai/openai-python/issues/761)) ([ddde839](https://github.com/openai/openai-python/commit/ddde8392be19e7ad77280374806667ecaef612da)) ## 1.2.1 (2023-11-09) Full Changelog: [v1.2.0...v1.2.1](https://github.com/openai/openai-python/compare/v1.2.0...v1.2.1) ### Documentation * **readme:** fix nested params example ([#756](https://github.com/openai/openai-python/issues/756)) ([ffbe5ec](https://github.com/openai/openai-python/commit/ffbe5eca0f8790ebcdb27ffe845da178a3ef4c45)) ### Refactors * **client:** deprecate files.retrieve_content in favour of files.content ([#753](https://github.com/openai/openai-python/issues/753)) ([eea5bc1](https://github.com/openai/openai-python/commit/eea5bc173466f63a6e84bd2d741b4873ca056b4c)) ## 1.2.0 (2023-11-08) Full Changelog: [v1.1.2...v1.2.0](https://github.com/openai/openai-python/compare/v1.1.2...v1.2.0) ### Features * **api:** unify function types ([#741](https://github.com/openai/openai-python/issues/741)) ([ed16c4d](https://github.com/openai/openai-python/commit/ed16c4d2fec6cf4e33235d82b05ed9a777752204)) * **client:** support passing chunk size for binary responses ([#747](https://github.com/openai/openai-python/issues/747)) ([c0c89b7](https://github.com/openai/openai-python/commit/c0c89b77a69ef098900e3a194894efcf72085d36)) ### Bug Fixes * **api:** update embedding response object type ([#739](https://github.com/openai/openai-python/issues/739)) ([29182c4](https://github.com/openai/openai-python/commit/29182c4818e2c56f46e961dba33e31dc30c25519)) * **client:** show a helpful error message if the v0 API is used ([#743](https://github.com/openai/openai-python/issues/743)) ([920567c](https://github.com/openai/openai-python/commit/920567cb04df48a7f6cd2a3402a0b1f172c6290e)) ### Chores * **internal:** improve github devcontainer setup ([#737](https://github.com/openai/openai-python/issues/737)) ([0ac1abb](https://github.com/openai/openai-python/commit/0ac1abb07ec687a4f7b1150be10054dbd6e7cfbc)) ### Refactors * **api:** rename FunctionObject to FunctionDefinition ([#746](https://github.com/openai/openai-python/issues/746)) ([1afd138](https://github.com/openai/openai-python/commit/1afd13856c0e586ecbde8b24fe4f4bad9beeefdf)) ## 1.1.2 (2023-11-08) Full Changelog: [v1.1.1...v1.1.2](https://github.com/openai/openai-python/compare/v1.1.1...v1.1.2) ### Bug Fixes * **api:** accidentally required params, add new models & other fixes ([#729](https://github.com/openai/openai-python/issues/729)) ([03c3e03](https://github.com/openai/openai-python/commit/03c3e03fc758cf4e59b81edf73a2618d80b560b7)) * asssitant_deleted -> assistant_deleted ([#711](https://github.com/openai/openai-python/issues/711)) ([287b51e](https://github.com/openai/openai-python/commit/287b51e4f7cede9667c118007de1275eb04772c6)) ### Chores * **docs:** fix github links ([#719](https://github.com/openai/openai-python/issues/719)) ([0cda8ca](https://github.com/openai/openai-python/commit/0cda8cab718d53d7dc0604d9fac52838c9391565)) * **internal:** fix some typos ([#718](https://github.com/openai/openai-python/issues/718)) ([894ad87](https://github.com/openai/openai-python/commit/894ad874aaa5d74530f561896ff31f68693418da)) ================================================ FILE: CONTRIBUTING.md ================================================ ## Setting up the environment ### With Rye We use [Rye](https://rye.astral.sh/) to manage dependencies because it will automatically provision a Python environment with the expected Python version. To set it up, run: ```sh $ ./scripts/bootstrap ``` Or [install Rye manually](https://rye.astral.sh/guide/installation/) and run: ```sh $ rye sync --all-features ``` You can then run scripts using `rye run python script.py` or by activating the virtual environment: ```sh # Activate the virtual environment - https://docs.python.org/3/library/venv.html#how-venvs-work $ source .venv/bin/activate # now you can omit the `rye run` prefix $ python script.py ``` ### Without Rye Alternatively if you don't want to install `Rye`, you can stick with the standard `pip` setup by ensuring you have the Python version specified in `.python-version`, create a virtual environment however you desire and then install dependencies using this command: ```sh $ pip install -r requirements-dev.lock ``` ## Modifying/Adding code Most of the SDK is generated code. Modifications to code will be persisted between generations, but may result in merge conflicts between manual patches and changes from the generator. The generator will never modify the contents of the `src/openai/lib/` and `examples/` directories. ## Adding and running examples All files in the `examples/` directory are not modified by the generator and can be freely edited or added to. ```py # add an example to examples/.py #!/usr/bin/env -S rye run python … ``` ```sh $ chmod +x examples/.py # run the example against your api $ ./examples/.py ``` ## Using the repository from source If you’d like to use the repository from source, you can either install from git or link to a cloned repository: To install via git: ```sh $ pip install git+ssh://git@github.com/openai/openai-python.git ``` Alternatively, you can build from source and install the wheel file: Building this package will create two files in the `dist/` directory, a `.tar.gz` containing the source files and a `.whl` that can be used to install the package efficiently. To create a distributable version of the library, all you have to do is run this command: ```sh $ rye build # or $ python -m build ``` Then to install: ```sh $ pip install ./path-to-wheel-file.whl ``` ## Running tests Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests. ```sh $ ./scripts/mock ``` ```sh $ ./scripts/test ``` ## Linting and formatting This repository uses [ruff](https://github.com/astral-sh/ruff) and [black](https://github.com/psf/black) to format the code in the repository. To lint: ```sh $ ./scripts/lint ``` To format and fix all ruff issues automatically: ```sh $ ./scripts/format ``` ## Publishing and releases Changes made to this repository via the automated release PR pipeline should publish to PyPI automatically. If the changes aren't made through the automated pipeline, you may want to make releases manually. ### Publish with a GitHub workflow You can release to package managers by using [the `Publish PyPI` GitHub action](https://www.github.com/openai/openai-python/actions/workflows/publish-pypi.yml). This requires a setup organization or repository secret to be set up. ### Publish manually If you need to manually release a package, you can run the `bin/publish-pypi` script with a `PYPI_TOKEN` set on the environment. ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2026 OpenAI Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ # OpenAI Python API library [![PyPI version](https://img.shields.io/pypi/v/openai.svg?label=pypi%20(stable))](https://pypi.org/project/openai/) The OpenAI Python library provides convenient access to the OpenAI REST API from any Python 3.9+ application. The library includes type definitions for all request params and response fields, and offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx). It is generated from our [OpenAPI specification](https://github.com/openai/openai-openapi) with [Stainless](https://stainlessapi.com/). ## Documentation The REST API documentation can be found on [platform.openai.com](https://platform.openai.com/docs/api-reference). The full API of this library can be found in [api.md](api.md). ## Installation ```sh # install from PyPI pip install openai ``` ## Usage The full API of this library can be found in [api.md](api.md). The primary API for interacting with OpenAI models is the [Responses API](https://platform.openai.com/docs/api-reference/responses). You can generate text from the model with the code below. ```python import os from openai import OpenAI client = OpenAI( # This is the default and can be omitted api_key=os.environ.get("OPENAI_API_KEY"), ) response = client.responses.create( model="gpt-5.2", instructions="You are a coding assistant that talks like a pirate.", input="How do I check if a Python object is an instance of a class?", ) print(response.output_text) ``` The previous standard (supported indefinitely) for generating text is the [Chat Completions API](https://platform.openai.com/docs/api-reference/chat). You can use that API to generate text from the model with the code below. ```python from openai import OpenAI client = OpenAI() completion = client.chat.completions.create( model="gpt-5.2", messages=[ {"role": "developer", "content": "Talk like a pirate."}, { "role": "user", "content": "How do I check if a Python object is an instance of a class?", }, ], ) print(completion.choices[0].message.content) ``` While you can provide an `api_key` keyword argument, we recommend using [python-dotenv](https://pypi.org/project/python-dotenv/) to add `OPENAI_API_KEY="My API Key"` to your `.env` file so that your API key is not stored in source control. [Get an API key here](https://platform.openai.com/settings/organization/api-keys). ### Vision With an image URL: ```python prompt = "What is in this image?" img_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/2023_06_08_Raccoon1.jpg/1599px-2023_06_08_Raccoon1.jpg" response = client.responses.create( model="gpt-5.2", input=[ { "role": "user", "content": [ {"type": "input_text", "text": prompt}, {"type": "input_image", "image_url": f"{img_url}"}, ], } ], ) ``` With the image as a base64 encoded string: ```python import base64 from openai import OpenAI client = OpenAI() prompt = "What is in this image?" with open("path/to/image.png", "rb") as image_file: b64_image = base64.b64encode(image_file.read()).decode("utf-8") response = client.responses.create( model="gpt-5.2", input=[ { "role": "user", "content": [ {"type": "input_text", "text": prompt}, {"type": "input_image", "image_url": f"data:image/png;base64,{b64_image}"}, ], } ], ) ``` ## Async usage Simply import `AsyncOpenAI` instead of `OpenAI` and use `await` with each API call: ```python import os import asyncio from openai import AsyncOpenAI client = AsyncOpenAI( # This is the default and can be omitted api_key=os.environ.get("OPENAI_API_KEY"), ) async def main() -> None: response = await client.responses.create( model="gpt-5.2", input="Explain disestablishmentarianism to a smart five year old." ) print(response.output_text) asyncio.run(main()) ``` Functionality between the synchronous and asynchronous clients is otherwise identical. ### With aiohttp By default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend. You can enable this by installing `aiohttp`: ```sh # install from PyPI pip install openai[aiohttp] ``` Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`: ```python import os import asyncio from openai import DefaultAioHttpClient from openai import AsyncOpenAI async def main() -> None: async with AsyncOpenAI( api_key=os.environ.get("OPENAI_API_KEY"), # This is the default and can be omitted http_client=DefaultAioHttpClient(), ) as client: chat_completion = await client.chat.completions.create( messages=[ { "role": "user", "content": "Say this is a test", } ], model="gpt-5.2", ) asyncio.run(main()) ``` ## Streaming responses We provide support for streaming responses using Server Side Events (SSE). ```python from openai import OpenAI client = OpenAI() stream = client.responses.create( model="gpt-5.2", input="Write a one-sentence bedtime story about a unicorn.", stream=True, ) for event in stream: print(event) ``` The async client uses the exact same interface. ```python import asyncio from openai import AsyncOpenAI client = AsyncOpenAI() async def main(): stream = await client.responses.create( model="gpt-5.2", input="Write a one-sentence bedtime story about a unicorn.", stream=True, ) async for event in stream: print(event) asyncio.run(main()) ``` ## Realtime API The Realtime API enables you to build low-latency, multi-modal conversational experiences. It currently supports text and audio as both input and output, as well as [function calling](https://platform.openai.com/docs/guides/function-calling) through a WebSocket connection. Under the hood the SDK uses the [`websockets`](https://websockets.readthedocs.io/en/stable/) library to manage connections. The Realtime API works through a combination of client-sent events and server-sent events. Clients can send events to do things like update session configuration or send text and audio inputs. Server events confirm when audio responses have completed, or when a text response from the model has been received. A full event reference can be found [here](https://platform.openai.com/docs/api-reference/realtime-client-events) and a guide can be found [here](https://platform.openai.com/docs/guides/realtime). Basic text based example: ```py import asyncio from openai import AsyncOpenAI async def main(): client = AsyncOpenAI() async with client.realtime.connect(model="gpt-realtime") as connection: await connection.session.update( session={"type": "realtime", "output_modalities": ["text"]} ) await connection.conversation.item.create( item={ "type": "message", "role": "user", "content": [{"type": "input_text", "text": "Say hello!"}], } ) await connection.response.create() async for event in connection: if event.type == "response.output_text.delta": print(event.delta, flush=True, end="") elif event.type == "response.output_text.done": print() elif event.type == "response.done": break asyncio.run(main()) ``` However the real magic of the Realtime API is handling audio inputs / outputs, see this example [TUI script](https://github.com/openai/openai-python/blob/main/examples/realtime/push_to_talk_app.py) for a fully fledged example. ### Realtime error handling Whenever an error occurs, the Realtime API will send an [`error` event](https://platform.openai.com/docs/guides/realtime-model-capabilities#error-handling) and the connection will stay open and remain usable. This means you need to handle it yourself, as _no errors are raised directly_ by the SDK when an `error` event comes in. ```py client = AsyncOpenAI() async with client.realtime.connect(model="gpt-realtime") as connection: ... async for event in connection: if event.type == 'error': print(event.error.type) print(event.error.code) print(event.error.event_id) print(event.error.message) ``` ## Using types Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like: - Serializing back into JSON, `model.to_json()` - Converting to a dictionary, `model.to_dict()` Typed requests and responses provide autocomplete and documentation within your editor. If you would like to see type errors in VS Code to help catch bugs earlier, set `python.analysis.typeCheckingMode` to `basic`. ## Pagination List methods in the OpenAI API are paginated. This library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually: ```python from openai import OpenAI client = OpenAI() all_jobs = [] # Automatically fetches more pages as needed. for job in client.fine_tuning.jobs.list( limit=20, ): # Do something with job here all_jobs.append(job) print(all_jobs) ``` Or, asynchronously: ```python import asyncio from openai import AsyncOpenAI client = AsyncOpenAI() async def main() -> None: all_jobs = [] # Iterate through items across all pages, issuing requests as needed. async for job in client.fine_tuning.jobs.list( limit=20, ): all_jobs.append(job) print(all_jobs) asyncio.run(main()) ``` Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages: ```python first_page = await client.fine_tuning.jobs.list( limit=20, ) if first_page.has_next_page(): print(f"will fetch next page using these details: {first_page.next_page_info()}") next_page = await first_page.get_next_page() print(f"number of items we just fetched: {len(next_page.data)}") # Remove `await` for non-async usage. ``` Or just work directly with the returned data: ```python first_page = await client.fine_tuning.jobs.list( limit=20, ) print(f"next page cursor: {first_page.after}") # => "next page cursor: ..." for job in first_page.data: print(job.id) # Remove `await` for non-async usage. ``` ## Nested params Nested parameters are dictionaries, typed using `TypedDict`, for example: ```python from openai import OpenAI client = OpenAI() response = client.chat.responses.create( input=[ { "role": "user", "content": "How much ?", } ], model="gpt-5.2", response_format={"type": "json_object"}, ) ``` ## File uploads Request parameters that correspond to file uploads can be passed as `bytes`, or a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance or a tuple of `(filename, contents, media type)`. ```python from pathlib import Path from openai import OpenAI client = OpenAI() client.files.create( file=Path("input.jsonl"), purpose="fine-tune", ) ``` The async client uses the exact same interface. If you pass a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance, the file contents will be read asynchronously automatically. ## Webhook Verification Verifying webhook signatures is _optional but encouraged_. For more information about webhooks, see [the API docs](https://platform.openai.com/docs/guides/webhooks). ### Parsing webhook payloads For most use cases, you will likely want to verify the webhook and parse the payload at the same time. To achieve this, we provide the method `client.webhooks.unwrap()`, which parses a webhook request and verifies that it was sent by OpenAI. This method will raise an error if the signature is invalid. Note that the `body` parameter must be the raw JSON string sent from the server (do not parse it first). The `.unwrap()` method will parse this JSON for you into an event object after verifying the webhook was sent from OpenAI. ```python from openai import OpenAI from flask import Flask, request app = Flask(__name__) client = OpenAI() # OPENAI_WEBHOOK_SECRET environment variable is used by default @app.route("/webhook", methods=["POST"]) def webhook(): request_body = request.get_data(as_text=True) try: event = client.webhooks.unwrap(request_body, request.headers) if event.type == "response.completed": print("Response completed:", event.data) elif event.type == "response.failed": print("Response failed:", event.data) else: print("Unhandled event type:", event.type) return "ok" except Exception as e: print("Invalid signature:", e) return "Invalid signature", 400 if __name__ == "__main__": app.run(port=8000) ``` ### Verifying webhook payloads directly In some cases, you may want to verify the webhook separately from parsing the payload. If you prefer to handle these steps separately, we provide the method `client.webhooks.verify_signature()` to _only verify_ the signature of a webhook request. Like `.unwrap()`, this method will raise an error if the signature is invalid. Note that the `body` parameter must be the raw JSON string sent from the server (do not parse it first). You will then need to parse the body after verifying the signature. ```python import json from openai import OpenAI from flask import Flask, request app = Flask(__name__) client = OpenAI() # OPENAI_WEBHOOK_SECRET environment variable is used by default @app.route("/webhook", methods=["POST"]) def webhook(): request_body = request.get_data(as_text=True) try: client.webhooks.verify_signature(request_body, request.headers) # Parse the body after verification event = json.loads(request_body) print("Verified event:", event) return "ok" except Exception as e: print("Invalid signature:", e) return "Invalid signature", 400 if __name__ == "__main__": app.run(port=8000) ``` ## Handling errors When the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `openai.APIConnectionError` is raised. When the API returns a non-success status code (that is, 4xx or 5xx response), a subclass of `openai.APIStatusError` is raised, containing `status_code` and `response` properties. All errors inherit from `openai.APIError`. ```python import openai from openai import OpenAI client = OpenAI() try: client.fine_tuning.jobs.create( model="gpt-4o", training_file="file-abc123", ) except openai.APIConnectionError as e: print("The server could not be reached") print(e.__cause__) # an underlying Exception, likely raised within httpx. except openai.RateLimitError as e: print("A 429 status code was received; we should back off a bit.") except openai.APIStatusError as e: print("Another non-200-range status code was received") print(e.status_code) print(e.response) ``` Error codes are as follows: | Status Code | Error Type | | ----------- | -------------------------- | | 400 | `BadRequestError` | | 401 | `AuthenticationError` | | 403 | `PermissionDeniedError` | | 404 | `NotFoundError` | | 422 | `UnprocessableEntityError` | | 429 | `RateLimitError` | | >=500 | `InternalServerError` | | N/A | `APIConnectionError` | ## Request IDs > For more information on debugging requests, see [these docs](https://platform.openai.com/docs/api-reference/debugging-requests) All object responses in the SDK provide a `_request_id` property which is added from the `x-request-id` response header so that you can quickly log failing requests and report them back to OpenAI. ```python response = await client.responses.create( model="gpt-5.2", input="Say 'this is a test'.", ) print(response._request_id) # req_123 ``` Note that unlike other properties that use an `_` prefix, the `_request_id` property _is_ public. Unless documented otherwise, _all_ other `_` prefix properties, methods and modules are _private_. > [!IMPORTANT] > If you need to access request IDs for failed requests you must catch the `APIStatusError` exception ```python import openai try: completion = await client.chat.completions.create( messages=[{"role": "user", "content": "Say this is a test"}], model="gpt-5.2" ) except openai.APIStatusError as exc: print(exc.request_id) # req_123 raise exc ``` ## Retries Certain errors are automatically retried 2 times by default, with a short exponential backoff. Connection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict, 429 Rate Limit, and >=500 Internal errors are all retried by default. You can use the `max_retries` option to configure or disable retry settings: ```python from openai import OpenAI # Configure the default for all requests: client = OpenAI( # default is 2 max_retries=0, ) # Or, configure per-request: client.with_options(max_retries=5).chat.completions.create( messages=[ { "role": "user", "content": "How can I get the name of the current day in JavaScript?", } ], model="gpt-5.2", ) ``` ## Timeouts By default requests time out after 10 minutes. You can configure this with a `timeout` option, which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object: ```python from openai import OpenAI # Configure the default for all requests: client = OpenAI( # 20 seconds (default is 10 minutes) timeout=20.0, ) # More granular control: client = OpenAI( timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0), ) # Override per-request: client.with_options(timeout=5.0).chat.completions.create( messages=[ { "role": "user", "content": "How can I list all files in a directory using Python?", } ], model="gpt-5.2", ) ``` On timeout, an `APITimeoutError` is thrown. Note that requests that time out are [retried twice by default](#retries). ## Advanced ### Logging We use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module. You can enable logging by setting the environment variable `OPENAI_LOG` to `info`. ```shell $ export OPENAI_LOG=info ``` Or to `debug` for more verbose logging. ### How to tell whether `None` means `null` or missing In an API response, a field may be explicitly `null`, or missing entirely; in either case, its value is `None` in this library. You can differentiate the two cases with `.model_fields_set`: ```py if response.my_field is None: if 'my_field' not in response.model_fields_set: print('Got json like {}, without a "my_field" key present at all.') else: print('Got json like {"my_field": null}.') ``` ### Accessing raw response data (e.g. headers) The "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call, e.g., ```py from openai import OpenAI client = OpenAI() response = client.chat.completions.with_raw_response.create( messages=[{ "role": "user", "content": "Say this is a test", }], model="gpt-5.2", ) print(response.headers.get('X-My-Header')) completion = response.parse() # get the object that `chat.completions.create()` would have returned print(completion) ``` These methods return a [`LegacyAPIResponse`](https://github.com/openai/openai-python/tree/main/src/openai/_legacy_response.py) object. This is a legacy class as we're changing it slightly in the next major version. For the sync client this will mostly be the same with the exception of `content` & `text` will be methods instead of properties. In the async client, all methods will be async. A migration script will be provided & the migration in general should be smooth. #### `.with_streaming_response` The above interface eagerly reads the full response body when you make the request, which may not always be what you want. To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods. As such, `.with_streaming_response` methods return a different [`APIResponse`](https://github.com/openai/openai-python/tree/main/src/openai/_response.py) object, and the async client returns an [`AsyncAPIResponse`](https://github.com/openai/openai-python/tree/main/src/openai/_response.py) object. ```python with client.chat.completions.with_streaming_response.create( messages=[ { "role": "user", "content": "Say this is a test", } ], model="gpt-5.2", ) as response: print(response.headers.get("X-My-Header")) for line in response.iter_lines(): print(line) ``` The context manager is required so that the response will reliably be closed. ### Making custom/undocumented requests This library is typed for convenient access to the documented API. If you need to access undocumented endpoints, params, or response properties, the library can still be used. #### Undocumented endpoints To make requests to undocumented endpoints, you can make requests using `client.get`, `client.post`, and other http verbs. Options on the client will be respected (such as retries) when making this request. ```py import httpx response = client.post( "/foo", cast_to=httpx.Response, body={"my_param": True}, ) print(response.headers.get("x-foo")) ``` #### Undocumented request params If you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` request options. #### Undocumented response properties To access undocumented response properties, you can access the extra fields like `response.unknown_prop`. You can also get all the extra fields on the Pydantic model as a dict with [`response.model_extra`](https://docs.pydantic.dev/latest/api/base_model/#pydantic.BaseModel.model_extra). ### Configuring the HTTP client You can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including: - Support for [proxies](https://www.python-httpx.org/advanced/proxies/) - Custom [transports](https://www.python-httpx.org/advanced/transports/) - Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality ```python import httpx from openai import OpenAI, DefaultHttpxClient client = OpenAI( # Or use the `OPENAI_BASE_URL` env var base_url="http://my.test.server.example.com:8083/v1", http_client=DefaultHttpxClient( proxy="http://my.test.proxy.example.com", transport=httpx.HTTPTransport(local_address="0.0.0.0"), ), ) ``` You can also customize the client on a per-request basis by using `with_options()`: ```python client.with_options(http_client=DefaultHttpxClient(...)) ``` ### Managing HTTP resources By default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting. ```py from openai import OpenAI with OpenAI() as client: # make requests here ... # HTTP client is now closed ``` ## Microsoft Azure OpenAI To use this library with [Azure OpenAI](https://learn.microsoft.com/azure/ai-services/openai/overview), use the `AzureOpenAI` class instead of the `OpenAI` class. > [!IMPORTANT] > The Azure API shape differs from the core API shape which means that the static types for responses / params > won't always be correct. ```py from openai import AzureOpenAI # gets the API Key from environment variable AZURE_OPENAI_API_KEY client = AzureOpenAI( # https://learn.microsoft.com/azure/ai-services/openai/reference#rest-api-versioning api_version="2023-07-01-preview", # https://learn.microsoft.com/azure/cognitive-services/openai/how-to/create-resource?pivots=web-portal#create-a-resource azure_endpoint="https://example-endpoint.openai.azure.com", ) completion = client.chat.completions.create( model="deployment-name", # e.g. gpt-35-instant messages=[ { "role": "user", "content": "How do I output all files in a directory using Python?", }, ], ) print(completion.to_json()) ``` In addition to the options provided in the base `OpenAI` client, the following options are provided: - `azure_endpoint` (or the `AZURE_OPENAI_ENDPOINT` environment variable) - `azure_deployment` - `api_version` (or the `OPENAI_API_VERSION` environment variable) - `azure_ad_token` (or the `AZURE_OPENAI_AD_TOKEN` environment variable) - `azure_ad_token_provider` An example of using the client with Microsoft Entra ID (formerly known as Azure Active Directory) can be found [here](https://github.com/openai/openai-python/blob/main/examples/azure_ad.py). ## Versioning This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions: 1. Changes that only affect static types, without breaking runtime behavior. 2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_ 3. Changes that we do not expect to impact the vast majority of users in practice. We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience. We are keen for your feedback; please open an [issue](https://www.github.com/openai/openai-python/issues) with questions, bugs, or suggestions. ### Determining the installed version If you've upgraded to the latest version but aren't seeing any new features you were expecting then your python environment is likely still using an older version. You can determine the version that is being used at runtime with: ```py import openai print(openai.__version__) ``` ## Requirements Python 3.9 or higher. ## Contributing See [the contributing documentation](./CONTRIBUTING.md). ================================================ FILE: SECURITY.md ================================================ # Security Policy ## Reporting Security Issues This SDK is generated by [Stainless Software Inc](http://stainless.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken. To report a security issue, please contact the Stainless team at security@stainless.com. ## Responsible Disclosure We appreciate the efforts of security researchers and individuals who help us maintain the security of SDKs we generate. If you believe you have found a security vulnerability, please adhere to responsible disclosure practices by allowing us a reasonable amount of time to investigate and address the issue before making any information public. ## Reporting Non-SDK Related Security Issues If you encounter security issues that are not directly related to SDKs but pertain to the services or products provided by OpenAI, please follow the respective company's security reporting guidelines. ### OpenAI Terms and Policies Our Security Policy can be found at [Security Policy URL](https://openai.com/policies/coordinated-vulnerability-disclosure-policy). Please contact disclosure@openai.com for any questions or concerns regarding the security of our services. --- Thank you for helping us keep the SDKs and systems they interact with secure. ================================================ FILE: api.md ================================================ # Shared Types ```python from openai.types import ( AllModels, ChatModel, ComparisonFilter, CompoundFilter, CustomToolInputFormat, ErrorObject, FunctionDefinition, FunctionParameters, Metadata, Reasoning, ReasoningEffort, ResponseFormatJSONObject, ResponseFormatJSONSchema, ResponseFormatText, ResponseFormatTextGrammar, ResponseFormatTextPython, ResponsesModel, ) ``` # Completions Types: ```python from openai.types import Completion, CompletionChoice, CompletionUsage ``` Methods: - client.completions.create(\*\*params) -> Completion # Chat Types: ```python from openai.types import ChatModel ``` ## Completions Types: ```python from openai.types.chat import ( ChatCompletion, ChatCompletionAllowedToolChoice, ChatCompletionAssistantMessageParam, ChatCompletionAudio, ChatCompletionAudioParam, ChatCompletionChunk, ChatCompletionContentPart, ChatCompletionContentPartImage, ChatCompletionContentPartInputAudio, ChatCompletionContentPartRefusal, ChatCompletionContentPartText, ChatCompletionCustomTool, ChatCompletionDeleted, ChatCompletionDeveloperMessageParam, ChatCompletionFunctionCallOption, ChatCompletionFunctionMessageParam, ChatCompletionFunctionTool, ChatCompletionMessage, ChatCompletionMessageCustomToolCall, ChatCompletionMessageFunctionToolCall, ChatCompletionMessageParam, ChatCompletionMessageToolCallUnion, ChatCompletionModality, ChatCompletionNamedToolChoice, ChatCompletionNamedToolChoiceCustom, ChatCompletionPredictionContent, ChatCompletionRole, ChatCompletionStoreMessage, ChatCompletionStreamOptions, ChatCompletionSystemMessageParam, ChatCompletionTokenLogprob, ChatCompletionToolUnion, ChatCompletionToolChoiceOption, ChatCompletionToolMessageParam, ChatCompletionUserMessageParam, ChatCompletionAllowedTools, ChatCompletionReasoningEffort, ) ``` Methods: - client.chat.completions.create(\*\*params) -> ChatCompletion - client.chat.completions.retrieve(completion_id) -> ChatCompletion - client.chat.completions.update(completion_id, \*\*params) -> ChatCompletion - client.chat.completions.list(\*\*params) -> SyncCursorPage[ChatCompletion] - client.chat.completions.delete(completion_id) -> ChatCompletionDeleted ### Messages Methods: - client.chat.completions.messages.list(completion_id, \*\*params) -> SyncCursorPage[ChatCompletionStoreMessage] # Embeddings Types: ```python from openai.types import CreateEmbeddingResponse, Embedding, EmbeddingModel ``` Methods: - client.embeddings.create(\*\*params) -> CreateEmbeddingResponse # Files Types: ```python from openai.types import FileContent, FileDeleted, FileObject, FilePurpose ``` Methods: - client.files.create(\*\*params) -> FileObject - client.files.retrieve(file_id) -> FileObject - client.files.list(\*\*params) -> SyncCursorPage[FileObject] - client.files.delete(file_id) -> FileDeleted - client.files.content(file_id) -> HttpxBinaryResponseContent - client.files.retrieve_content(file_id) -> str - client.files.wait_for_processing(\*args) -> FileObject # Images Types: ```python from openai.types import ( Image, ImageEditCompletedEvent, ImageEditPartialImageEvent, ImageEditStreamEvent, ImageGenCompletedEvent, ImageGenPartialImageEvent, ImageGenStreamEvent, ImageModel, ImagesResponse, ) ``` Methods: - client.images.create_variation(\*\*params) -> ImagesResponse - client.images.edit(\*\*params) -> ImagesResponse - client.images.generate(\*\*params) -> ImagesResponse # Audio Types: ```python from openai.types import AudioModel, AudioResponseFormat ``` ## Transcriptions Types: ```python from openai.types.audio import ( Transcription, TranscriptionDiarized, TranscriptionDiarizedSegment, TranscriptionInclude, TranscriptionSegment, TranscriptionStreamEvent, TranscriptionTextDeltaEvent, TranscriptionTextDoneEvent, TranscriptionTextSegmentEvent, TranscriptionVerbose, TranscriptionWord, TranscriptionCreateResponse, ) ``` Methods: - client.audio.transcriptions.create(\*\*params) -> TranscriptionCreateResponse ## Translations Types: ```python from openai.types.audio import Translation, TranslationVerbose, TranslationCreateResponse ``` Methods: - client.audio.translations.create(\*\*params) -> TranslationCreateResponse ## Speech Types: ```python from openai.types.audio import SpeechModel ``` Methods: - client.audio.speech.create(\*\*params) -> HttpxBinaryResponseContent # Moderations Types: ```python from openai.types import ( Moderation, ModerationImageURLInput, ModerationModel, ModerationMultiModalInput, ModerationTextInput, ModerationCreateResponse, ) ``` Methods: - client.moderations.create(\*\*params) -> ModerationCreateResponse # Models Types: ```python from openai.types import Model, ModelDeleted ``` Methods: - client.models.retrieve(model) -> Model - client.models.list() -> SyncPage[Model] - client.models.delete(model) -> ModelDeleted # FineTuning ## Methods Types: ```python from openai.types.fine_tuning import ( DpoHyperparameters, DpoMethod, ReinforcementHyperparameters, ReinforcementMethod, SupervisedHyperparameters, SupervisedMethod, ) ``` ## Jobs Types: ```python from openai.types.fine_tuning import ( FineTuningJob, FineTuningJobEvent, FineTuningJobWandbIntegration, FineTuningJobWandbIntegrationObject, FineTuningJobIntegration, ) ``` Methods: - client.fine_tuning.jobs.create(\*\*params) -> FineTuningJob - client.fine_tuning.jobs.retrieve(fine_tuning_job_id) -> FineTuningJob - client.fine_tuning.jobs.list(\*\*params) -> SyncCursorPage[FineTuningJob] - client.fine_tuning.jobs.cancel(fine_tuning_job_id) -> FineTuningJob - client.fine_tuning.jobs.list_events(fine_tuning_job_id, \*\*params) -> SyncCursorPage[FineTuningJobEvent] - client.fine_tuning.jobs.pause(fine_tuning_job_id) -> FineTuningJob - client.fine_tuning.jobs.resume(fine_tuning_job_id) -> FineTuningJob ### Checkpoints Types: ```python from openai.types.fine_tuning.jobs import FineTuningJobCheckpoint ``` Methods: - client.fine_tuning.jobs.checkpoints.list(fine_tuning_job_id, \*\*params) -> SyncCursorPage[FineTuningJobCheckpoint] ## Checkpoints ### Permissions Types: ```python from openai.types.fine_tuning.checkpoints import ( PermissionCreateResponse, PermissionRetrieveResponse, PermissionListResponse, PermissionDeleteResponse, ) ``` Methods: - client.fine_tuning.checkpoints.permissions.create(fine_tuned_model_checkpoint, \*\*params) -> SyncPage[PermissionCreateResponse] - client.fine_tuning.checkpoints.permissions.retrieve(fine_tuned_model_checkpoint, \*\*params) -> PermissionRetrieveResponse - client.fine_tuning.checkpoints.permissions.list(fine_tuned_model_checkpoint, \*\*params) -> SyncConversationCursorPage[PermissionListResponse] - client.fine_tuning.checkpoints.permissions.delete(permission_id, \*, fine_tuned_model_checkpoint) -> PermissionDeleteResponse ## Alpha ### Graders Types: ```python from openai.types.fine_tuning.alpha import GraderRunResponse, GraderValidateResponse ``` Methods: - client.fine_tuning.alpha.graders.run(\*\*params) -> GraderRunResponse - client.fine_tuning.alpha.graders.validate(\*\*params) -> GraderValidateResponse # Graders ## GraderModels Types: ```python from openai.types.graders import ( GraderInputs, LabelModelGrader, MultiGrader, PythonGrader, ScoreModelGrader, StringCheckGrader, TextSimilarityGrader, ) ``` # VectorStores Types: ```python from openai.types import ( AutoFileChunkingStrategyParam, FileChunkingStrategy, FileChunkingStrategyParam, OtherFileChunkingStrategyObject, StaticFileChunkingStrategy, StaticFileChunkingStrategyObject, StaticFileChunkingStrategyObjectParam, VectorStore, VectorStoreDeleted, VectorStoreSearchResponse, ) ``` Methods: - client.vector_stores.create(\*\*params) -> VectorStore - client.vector_stores.retrieve(vector_store_id) -> VectorStore - client.vector_stores.update(vector_store_id, \*\*params) -> VectorStore - client.vector_stores.list(\*\*params) -> SyncCursorPage[VectorStore] - client.vector_stores.delete(vector_store_id) -> VectorStoreDeleted - client.vector_stores.search(vector_store_id, \*\*params) -> SyncPage[VectorStoreSearchResponse] ## Files Types: ```python from openai.types.vector_stores import VectorStoreFile, VectorStoreFileDeleted, FileContentResponse ``` Methods: - client.vector_stores.files.create(vector_store_id, \*\*params) -> VectorStoreFile - client.vector_stores.files.retrieve(file_id, \*, vector_store_id) -> VectorStoreFile - client.vector_stores.files.update(file_id, \*, vector_store_id, \*\*params) -> VectorStoreFile - client.vector_stores.files.list(vector_store_id, \*\*params) -> SyncCursorPage[VectorStoreFile] - client.vector_stores.files.delete(file_id, \*, vector_store_id) -> VectorStoreFileDeleted - client.vector_stores.files.content(file_id, \*, vector_store_id) -> SyncPage[FileContentResponse] - client.vector_stores.files.create_and_poll(\*args) -> VectorStoreFile - client.vector_stores.files.poll(\*args) -> VectorStoreFile - client.vector_stores.files.upload(\*args) -> VectorStoreFile - client.vector_stores.files.upload_and_poll(\*args) -> VectorStoreFile ## FileBatches Types: ```python from openai.types.vector_stores import VectorStoreFileBatch ``` Methods: - client.vector_stores.file_batches.create(vector_store_id, \*\*params) -> VectorStoreFileBatch - client.vector_stores.file_batches.retrieve(batch_id, \*, vector_store_id) -> VectorStoreFileBatch - client.vector_stores.file_batches.cancel(batch_id, \*, vector_store_id) -> VectorStoreFileBatch - client.vector_stores.file_batches.list_files(batch_id, \*, vector_store_id, \*\*params) -> SyncCursorPage[VectorStoreFile] - client.vector_stores.file_batches.create_and_poll(\*args) -> VectorStoreFileBatch - client.vector_stores.file_batches.poll(\*args) -> VectorStoreFileBatch - client.vector_stores.file_batches.upload_and_poll(\*args) -> VectorStoreFileBatch # [Webhooks](src/openai/resources/webhooks/api.md) Methods: - client.webhooks.unwrap(payload, headers, \*, secret) -> UnwrapWebhookEvent - client.webhooks.verify_signature(payload, headers, \*, secret, tolerance) -> None # Beta ## Realtime Types: ```python from openai.types.beta.realtime import ( ConversationCreatedEvent, ConversationItem, ConversationItemContent, ConversationItemCreateEvent, ConversationItemCreatedEvent, ConversationItemDeleteEvent, ConversationItemDeletedEvent, ConversationItemInputAudioTranscriptionCompletedEvent, ConversationItemInputAudioTranscriptionDeltaEvent, ConversationItemInputAudioTranscriptionFailedEvent, ConversationItemRetrieveEvent, ConversationItemTruncateEvent, ConversationItemTruncatedEvent, ConversationItemWithReference, ErrorEvent, InputAudioBufferAppendEvent, InputAudioBufferClearEvent, InputAudioBufferClearedEvent, InputAudioBufferCommitEvent, InputAudioBufferCommittedEvent, InputAudioBufferSpeechStartedEvent, InputAudioBufferSpeechStoppedEvent, RateLimitsUpdatedEvent, RealtimeClientEvent, RealtimeResponse, RealtimeResponseStatus, RealtimeResponseUsage, RealtimeServerEvent, ResponseAudioDeltaEvent, ResponseAudioDoneEvent, ResponseAudioTranscriptDeltaEvent, ResponseAudioTranscriptDoneEvent, ResponseCancelEvent, ResponseContentPartAddedEvent, ResponseContentPartDoneEvent, ResponseCreateEvent, ResponseCreatedEvent, ResponseDoneEvent, ResponseFunctionCallArgumentsDeltaEvent, ResponseFunctionCallArgumentsDoneEvent, ResponseOutputItemAddedEvent, ResponseOutputItemDoneEvent, ResponseTextDeltaEvent, ResponseTextDoneEvent, SessionCreatedEvent, SessionUpdateEvent, SessionUpdatedEvent, TranscriptionSessionUpdate, TranscriptionSessionUpdatedEvent, ) ``` ### Sessions Types: ```python from openai.types.beta.realtime import Session, SessionCreateResponse ``` Methods: - client.beta.realtime.sessions.create(\*\*params) -> SessionCreateResponse ### TranscriptionSessions Types: ```python from openai.types.beta.realtime import TranscriptionSession ``` Methods: - client.beta.realtime.transcription_sessions.create(\*\*params) -> TranscriptionSession ## Assistants Types: ```python from openai.types.beta import ( Assistant, AssistantDeleted, AssistantStreamEvent, AssistantTool, CodeInterpreterTool, FileSearchTool, FunctionTool, MessageStreamEvent, RunStepStreamEvent, RunStreamEvent, ThreadStreamEvent, ) ``` Methods: - client.beta.assistants.create(\*\*params) -> Assistant - client.beta.assistants.retrieve(assistant_id) -> Assistant - client.beta.assistants.update(assistant_id, \*\*params) -> Assistant - client.beta.assistants.list(\*\*params) -> SyncCursorPage[Assistant] - client.beta.assistants.delete(assistant_id) -> AssistantDeleted ## Threads Types: ```python from openai.types.beta import ( AssistantResponseFormatOption, AssistantToolChoice, AssistantToolChoiceFunction, AssistantToolChoiceOption, Thread, ThreadDeleted, ) ``` Methods: - client.beta.threads.create(\*\*params) -> Thread - client.beta.threads.retrieve(thread_id) -> Thread - client.beta.threads.update(thread_id, \*\*params) -> Thread - client.beta.threads.delete(thread_id) -> ThreadDeleted - client.beta.threads.create_and_run(\*\*params) -> Run - client.beta.threads.create_and_run_poll(\*args) -> Run - client.beta.threads.create_and_run_stream(\*args) -> AssistantStreamManager[AssistantEventHandler] | AssistantStreamManager[AssistantEventHandlerT] ### Runs Types: ```python from openai.types.beta.threads import RequiredActionFunctionToolCall, Run, RunStatus ``` Methods: - client.beta.threads.runs.create(thread_id, \*\*params) -> Run - client.beta.threads.runs.retrieve(run_id, \*, thread_id) -> Run - client.beta.threads.runs.update(run_id, \*, thread_id, \*\*params) -> Run - client.beta.threads.runs.list(thread_id, \*\*params) -> SyncCursorPage[Run] - client.beta.threads.runs.cancel(run_id, \*, thread_id) -> Run - client.beta.threads.runs.submit_tool_outputs(run_id, \*, thread_id, \*\*params) -> Run - client.beta.threads.runs.create_and_poll(\*args) -> Run - client.beta.threads.runs.create_and_stream(\*args) -> AssistantStreamManager[AssistantEventHandler] | AssistantStreamManager[AssistantEventHandlerT] - client.beta.threads.runs.poll(\*args) -> Run - client.beta.threads.runs.stream(\*args) -> AssistantStreamManager[AssistantEventHandler] | AssistantStreamManager[AssistantEventHandlerT] - client.beta.threads.runs.submit_tool_outputs_and_poll(\*args) -> Run - client.beta.threads.runs.submit_tool_outputs_stream(\*args) -> AssistantStreamManager[AssistantEventHandler] | AssistantStreamManager[AssistantEventHandlerT] #### Steps Types: ```python from openai.types.beta.threads.runs import ( CodeInterpreterLogs, CodeInterpreterOutputImage, CodeInterpreterToolCall, CodeInterpreterToolCallDelta, FileSearchToolCall, FileSearchToolCallDelta, FunctionToolCall, FunctionToolCallDelta, MessageCreationStepDetails, RunStep, RunStepDelta, RunStepDeltaEvent, RunStepDeltaMessageDelta, RunStepInclude, ToolCall, ToolCallDelta, ToolCallDeltaObject, ToolCallsStepDetails, ) ``` Methods: - client.beta.threads.runs.steps.retrieve(step_id, \*, thread_id, run_id, \*\*params) -> RunStep - client.beta.threads.runs.steps.list(run_id, \*, thread_id, \*\*params) -> SyncCursorPage[RunStep] ### Messages Types: ```python from openai.types.beta.threads import ( Annotation, AnnotationDelta, FileCitationAnnotation, FileCitationDeltaAnnotation, FilePathAnnotation, FilePathDeltaAnnotation, ImageFile, ImageFileContentBlock, ImageFileDelta, ImageFileDeltaBlock, ImageURL, ImageURLContentBlock, ImageURLDelta, ImageURLDeltaBlock, Message, MessageContent, MessageContentDelta, MessageContentPartParam, MessageDeleted, MessageDelta, MessageDeltaEvent, RefusalContentBlock, RefusalDeltaBlock, Text, TextContentBlock, TextContentBlockParam, TextDelta, TextDeltaBlock, ) ``` Methods: - client.beta.threads.messages.create(thread_id, \*\*params) -> Message - client.beta.threads.messages.retrieve(message_id, \*, thread_id) -> Message - client.beta.threads.messages.update(message_id, \*, thread_id, \*\*params) -> Message - client.beta.threads.messages.list(thread_id, \*\*params) -> SyncCursorPage[Message] - client.beta.threads.messages.delete(message_id, \*, thread_id) -> MessageDeleted # Batches Types: ```python from openai.types import Batch, BatchError, BatchRequestCounts, BatchUsage ``` Methods: - client.batches.create(\*\*params) -> Batch - client.batches.retrieve(batch_id) -> Batch - client.batches.list(\*\*params) -> SyncCursorPage[Batch] - client.batches.cancel(batch_id) -> Batch # Uploads Types: ```python from openai.types import Upload ``` Methods: - client.uploads.create(\*\*params) -> Upload - client.uploads.cancel(upload_id) -> Upload - client.uploads.complete(upload_id, \*\*params) -> Upload ## Parts Types: ```python from openai.types.uploads import UploadPart ``` Methods: - client.uploads.parts.create(upload_id, \*\*params) -> UploadPart # [Responses](src/openai/resources/responses/api.md) # [Realtime](src/openai/resources/realtime/api.md) # [Conversations](src/openai/resources/conversations/api.md) # Evals Types: ```python from openai.types import ( EvalCustomDataSourceConfig, EvalStoredCompletionsDataSourceConfig, EvalCreateResponse, EvalRetrieveResponse, EvalUpdateResponse, EvalListResponse, EvalDeleteResponse, ) ``` Methods: - client.evals.create(\*\*params) -> EvalCreateResponse - client.evals.retrieve(eval_id) -> EvalRetrieveResponse - client.evals.update(eval_id, \*\*params) -> EvalUpdateResponse - client.evals.list(\*\*params) -> SyncCursorPage[EvalListResponse] - client.evals.delete(eval_id) -> EvalDeleteResponse ## Runs Types: ```python from openai.types.evals import ( CreateEvalCompletionsRunDataSource, CreateEvalJSONLRunDataSource, EvalAPIError, RunCreateResponse, RunRetrieveResponse, RunListResponse, RunDeleteResponse, RunCancelResponse, ) ``` Methods: - client.evals.runs.create(eval_id, \*\*params) -> RunCreateResponse - client.evals.runs.retrieve(run_id, \*, eval_id) -> RunRetrieveResponse - client.evals.runs.list(eval_id, \*\*params) -> SyncCursorPage[RunListResponse] - client.evals.runs.delete(run_id, \*, eval_id) -> RunDeleteResponse - client.evals.runs.cancel(run_id, \*, eval_id) -> RunCancelResponse ### OutputItems Types: ```python from openai.types.evals.runs import OutputItemRetrieveResponse, OutputItemListResponse ``` Methods: - client.evals.runs.output_items.retrieve(output_item_id, \*, eval_id, run_id) -> OutputItemRetrieveResponse - client.evals.runs.output_items.list(run_id, \*, eval_id, \*\*params) -> SyncCursorPage[OutputItemListResponse] # Containers Types: ```python from openai.types import ContainerCreateResponse, ContainerRetrieveResponse, ContainerListResponse ``` Methods: - client.containers.create(\*\*params) -> ContainerCreateResponse - client.containers.retrieve(container_id) -> ContainerRetrieveResponse - client.containers.list(\*\*params) -> SyncCursorPage[ContainerListResponse] - client.containers.delete(container_id) -> None ## Files Types: ```python from openai.types.containers import FileCreateResponse, FileRetrieveResponse, FileListResponse ``` Methods: - client.containers.files.create(container_id, \*\*params) -> FileCreateResponse - client.containers.files.retrieve(file_id, \*, container_id) -> FileRetrieveResponse - client.containers.files.list(container_id, \*\*params) -> SyncCursorPage[FileListResponse] - client.containers.files.delete(file_id, \*, container_id) -> None ### Content Methods: - client.containers.files.content.retrieve(file_id, \*, container_id) -> HttpxBinaryResponseContent # Skills Types: ```python from openai.types import DeletedSkill, Skill, SkillList ``` Methods: - client.skills.create(\*\*params) -> Skill - client.skills.retrieve(skill_id) -> Skill - client.skills.update(skill_id, \*\*params) -> Skill - client.skills.list(\*\*params) -> SyncCursorPage[Skill] - client.skills.delete(skill_id) -> DeletedSkill ## Content Methods: - client.skills.content.retrieve(skill_id) -> HttpxBinaryResponseContent ## Versions Types: ```python from openai.types.skills import DeletedSkillVersion, SkillVersion, SkillVersionList ``` Methods: - client.skills.versions.create(skill_id, \*\*params) -> SkillVersion - client.skills.versions.retrieve(version, \*, skill_id) -> SkillVersion - client.skills.versions.list(skill_id, \*\*params) -> SyncCursorPage[SkillVersion] - client.skills.versions.delete(version, \*, skill_id) -> DeletedSkillVersion ### Content Methods: - client.skills.versions.content.retrieve(version, \*, skill_id) -> HttpxBinaryResponseContent # Videos Types: ```python from openai.types import ( ImageInputReferenceParam, Video, VideoCreateError, VideoModel, VideoSeconds, VideoSize, VideoDeleteResponse, VideoCreateCharacterResponse, VideoGetCharacterResponse, ) ``` Methods: - client.videos.create(\*\*params) -> Video - client.videos.retrieve(video_id) -> Video - client.videos.list(\*\*params) -> SyncConversationCursorPage[Video] - client.videos.delete(video_id) -> VideoDeleteResponse - client.videos.create_character(\*\*params) -> VideoCreateCharacterResponse - client.videos.download_content(video_id, \*\*params) -> HttpxBinaryResponseContent - client.videos.edit(\*\*params) -> Video - client.videos.extend(\*\*params) -> Video - client.videos.get_character(character_id) -> VideoGetCharacterResponse - client.videos.remix(video_id, \*\*params) -> Video - client.videos.create_and_poll(\*args) -> Video - client.videos.poll(\*args) -> Video ================================================ FILE: bin/check-release-environment ================================================ #!/usr/bin/env bash errors=() if [ -z "${STAINLESS_API_KEY}" ]; then errors+=("The STAINLESS_API_KEY secret has not been set. Please contact Stainless for an API key & set it in your organization secrets on GitHub.") fi if [ -z "${PYPI_TOKEN}" ]; then errors+=("The PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.") fi lenErrors=${#errors[@]} if [[ lenErrors -gt 0 ]]; then echo -e "Found the following errors in the release environment:\n" for error in "${errors[@]}"; do echo -e "- $error\n" done exit 1 fi echo "The environment is ready to push releases!" ================================================ FILE: bin/publish-pypi ================================================ #!/usr/bin/env bash set -eux mkdir -p dist rye build --clean rye publish --yes --token=$PYPI_TOKEN ================================================ FILE: examples/.keep ================================================ File generated from our OpenAPI spec by Stainless. This directory can be used to store example files demonstrating usage of this SDK. It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. ================================================ FILE: examples/async_demo.py ================================================ #!/usr/bin/env -S poetry run python import asyncio from openai import AsyncOpenAI # gets API Key from environment variable OPENAI_API_KEY client = AsyncOpenAI() async def main() -> None: stream = await client.completions.create( model="gpt-3.5-turbo-instruct", prompt="Say this is a test", stream=True, ) async for completion in stream: print(completion.choices[0].text, end="") print() asyncio.run(main()) ================================================ FILE: examples/audio.py ================================================ #!/usr/bin/env rye run python from pathlib import Path from openai import OpenAI # gets OPENAI_API_KEY from your environment variables openai = OpenAI() speech_file_path = Path(__file__).parent / "speech.mp3" def main() -> None: # Create text-to-speech audio file with openai.audio.speech.with_streaming_response.create( model="tts-1", voice="alloy", input="the quick brown fox jumped over the lazy dogs", ) as response: response.stream_to_file(speech_file_path) # Create transcription from audio file transcription = openai.audio.transcriptions.create( model="whisper-1", file=speech_file_path, ) print(transcription.text) # Create translation from audio file translation = openai.audio.translations.create( model="whisper-1", file=speech_file_path, ) print(translation.text) if __name__ == "__main__": main() ================================================ FILE: examples/azure.py ================================================ from openai import AzureOpenAI # may change in the future # https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#rest-api-versioning api_version = "2023-07-01-preview" # gets the API Key from environment variable AZURE_OPENAI_API_KEY client = AzureOpenAI( api_version=api_version, # https://learn.microsoft.com/en-us/azure/cognitive-services/openai/how-to/create-resource?pivots=web-portal#create-a-resource azure_endpoint="https://example-endpoint.openai.azure.com", ) completion = client.chat.completions.create( model="deployment-name", # e.g. gpt-35-instant messages=[ { "role": "user", "content": "How do I output all files in a directory using Python?", }, ], ) print(completion.to_json()) deployment_client = AzureOpenAI( api_version=api_version, # https://learn.microsoft.com/en-us/azure/cognitive-services/openai/how-to/create-resource?pivots=web-portal#create-a-resource azure_endpoint="https://example-resource.azure.openai.com/", # Navigate to the Azure OpenAI Studio to deploy a model. azure_deployment="deployment-name", # e.g. gpt-35-instant ) completion = deployment_client.chat.completions.create( model="", messages=[ { "role": "user", "content": "How do I output all files in a directory using Python?", }, ], ) print(completion.to_json()) ================================================ FILE: examples/azure_ad.py ================================================ import asyncio from openai.lib.azure import AzureOpenAI, AsyncAzureOpenAI, AzureADTokenProvider, AsyncAzureADTokenProvider scopes = "https://cognitiveservices.azure.com/.default" # May change in the future # https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#rest-api-versioning api_version = "2023-07-01-preview" # https://learn.microsoft.com/en-us/azure/cognitive-services/openai/how-to/create-resource?pivots=web-portal#create-a-resource endpoint = "https://my-resource.openai.azure.com" deployment_name = "deployment-name" # e.g. gpt-35-instant def sync_main() -> None: from azure.identity import DefaultAzureCredential, get_bearer_token_provider token_provider: AzureADTokenProvider = get_bearer_token_provider(DefaultAzureCredential(), scopes) client = AzureOpenAI( api_version=api_version, azure_endpoint=endpoint, azure_ad_token_provider=token_provider, ) completion = client.chat.completions.create( model=deployment_name, messages=[ { "role": "user", "content": "How do I output all files in a directory using Python?", } ], ) print(completion.to_json()) async def async_main() -> None: from azure.identity.aio import DefaultAzureCredential, get_bearer_token_provider token_provider: AsyncAzureADTokenProvider = get_bearer_token_provider(DefaultAzureCredential(), scopes) client = AsyncAzureOpenAI( api_version=api_version, azure_endpoint=endpoint, azure_ad_token_provider=token_provider, ) completion = await client.chat.completions.create( model=deployment_name, messages=[ { "role": "user", "content": "How do I output all files in a directory using Python?", } ], ) print(completion.to_json()) sync_main() asyncio.run(async_main()) ================================================ FILE: examples/demo.py ================================================ #!/usr/bin/env -S poetry run python from openai import OpenAI # gets API Key from environment variable OPENAI_API_KEY client = OpenAI() # Non-streaming: print("----- standard request -----") completion = client.chat.completions.create( model="gpt-4", messages=[ { "role": "user", "content": "Say this is a test", }, ], ) print(completion.choices[0].message.content) # Streaming: print("----- streaming request -----") stream = client.chat.completions.create( model="gpt-4", messages=[ { "role": "user", "content": "How do I output all files in a directory using Python?", }, ], stream=True, ) for chunk in stream: if not chunk.choices: continue print(chunk.choices[0].delta.content, end="") print() # Response headers: print("----- custom response headers test -----") response = client.chat.completions.with_raw_response.create( model="gpt-4", messages=[ { "role": "user", "content": "Say this is a test", } ], ) completion = response.parse() print(response.request_id) print(completion.choices[0].message.content) ================================================ FILE: examples/generate_file.sh ================================================ # generate a text file with random data for testing file uploads wanted_size=$((1024*2048*512)) file_size=$(( ((wanted_size/12)+1)*12 )) read_size=$((file_size*3/4)) echo "wanted=$wanted_size file=$file_size read=$read_size" dd if=/dev/urandom bs=$read_size count=1 | base64 > /tmp/small_test_file.txt truncate -s "$wanted_size" /tmp/big_test_file.txt ================================================ FILE: examples/image_stream.py ================================================ #!/usr/bin/env python import base64 from pathlib import Path from openai import OpenAI client = OpenAI() def main() -> None: """Example of OpenAI image streaming with partial images.""" stream = client.images.generate( model="gpt-image-1", prompt="A cute baby sea otter", n=1, size="1024x1024", stream=True, partial_images=3, ) for event in stream: if event.type == "image_generation.partial_image": print(f" Partial image {event.partial_image_index + 1}/3 received") print(f" Size: {len(event.b64_json)} characters (base64)") # Save partial image to file filename = f"partial_{event.partial_image_index + 1}.png" image_data = base64.b64decode(event.b64_json) with open(filename, "wb") as f: f.write(image_data) print(f" 💾 Saved to: {Path(filename).resolve()}") elif event.type == "image_generation.completed": print(f"\n✅ Final image completed!") print(f" Size: {len(event.b64_json)} characters (base64)") # Save final image to file filename = "final_image.png" image_data = base64.b64decode(event.b64_json) with open(filename, "wb") as f: f.write(image_data) print(f" 💾 Saved to: {Path(filename).resolve()}") else: print(f"❓ Unknown event: {event}") # type: ignore[unreachable] if __name__ == "__main__": try: main() except Exception as error: print(f"Error generating image: {error}") ================================================ FILE: examples/module_client.py ================================================ import openai # will default to `os.environ['OPENAI_API_KEY']` if not explicitly set openai.api_key = "..." # all client options can be configured just like the `OpenAI` instantiation counterpart openai.base_url = "https://..." openai.default_headers = {"x-foo": "true"} # all API calls work in the exact same fashion as well stream = openai.chat.completions.create( model="gpt-4", messages=[ { "role": "user", "content": "How do I output all files in a directory using Python?", }, ], stream=True, ) for chunk in stream: print(chunk.choices[0].delta.content or "", end="", flush=True) print() ================================================ FILE: examples/parsing.py ================================================ from typing import List import rich from pydantic import BaseModel from openai import OpenAI class Step(BaseModel): explanation: str output: str class MathResponse(BaseModel): steps: List[Step] final_answer: str client = OpenAI() completion = client.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[ {"role": "system", "content": "You are a helpful math tutor."}, {"role": "user", "content": "solve 8x + 31 = 2"}, ], response_format=MathResponse, ) message = completion.choices[0].message if message.parsed: rich.print(message.parsed.steps) print("answer: ", message.parsed.final_answer) else: print(message.refusal) ================================================ FILE: examples/parsing_stream.py ================================================ from typing import List import rich from pydantic import BaseModel from openai import OpenAI class Step(BaseModel): explanation: str output: str class MathResponse(BaseModel): steps: List[Step] final_answer: str client = OpenAI() with client.chat.completions.stream( model="gpt-4o-2024-08-06", messages=[ {"role": "system", "content": "You are a helpful math tutor."}, {"role": "user", "content": "solve 8x + 31 = 2"}, ], response_format=MathResponse, ) as stream: for event in stream: if event.type == "content.delta": print(event.delta, end="", flush=True) elif event.type == "content.done": print("\n") if event.parsed is not None: print(f"answer: {event.parsed.final_answer}") elif event.type == "refusal.delta": print(event.delta, end="", flush=True) elif event.type == "refusal.done": print() print("---------------") rich.print(stream.get_final_completion()) ================================================ FILE: examples/parsing_tools.py ================================================ from enum import Enum from typing import List, Union import rich from pydantic import BaseModel import openai from openai import OpenAI class Table(str, Enum): orders = "orders" customers = "customers" products = "products" class Column(str, Enum): id = "id" status = "status" expected_delivery_date = "expected_delivery_date" delivered_at = "delivered_at" shipped_at = "shipped_at" ordered_at = "ordered_at" canceled_at = "canceled_at" class Operator(str, Enum): eq = "=" gt = ">" lt = "<" le = "<=" ge = ">=" ne = "!=" class OrderBy(str, Enum): asc = "asc" desc = "desc" class DynamicValue(BaseModel): column_name: str class Condition(BaseModel): column: str operator: Operator value: Union[str, int, DynamicValue] class Query(BaseModel): table_name: Table columns: List[Column] conditions: List[Condition] order_by: OrderBy client = OpenAI() completion = client.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[ { "role": "system", "content": "You are a helpful assistant. The current date is August 6, 2024. You help users query for the data they are looking for by calling the query function.", }, { "role": "user", "content": "look up all my orders in november of last year that were fulfilled but not delivered on time", }, ], tools=[ openai.pydantic_function_tool(Query), ], ) tool_call = (completion.choices[0].message.tool_calls or [])[0] rich.print(tool_call.function) assert isinstance(tool_call.function.parsed_arguments, Query) print(tool_call.function.parsed_arguments.table_name) ================================================ FILE: examples/parsing_tools_stream.py ================================================ from __future__ import annotations import rich from pydantic import BaseModel import openai from openai import OpenAI class GetWeather(BaseModel): city: str country: str client = OpenAI() with client.chat.completions.stream( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in SF and New York?", }, ], tools=[ # because we're using `.parse_stream()`, the returned tool calls # will be automatically deserialized into this `GetWeather` type openai.pydantic_function_tool(GetWeather, name="get_weather"), ], parallel_tool_calls=True, ) as stream: for event in stream: if event.type == "tool_calls.function.arguments.delta" or event.type == "tool_calls.function.arguments.done": rich.get_console().print(event, width=80) print("----\n") rich.print(stream.get_final_completion()) ================================================ FILE: examples/picture.py ================================================ #!/usr/bin/env python from openai import OpenAI # gets OPENAI_API_KEY from your environment variables openai = OpenAI() prompt = "An astronaut lounging in a tropical resort in space, pixel art" model = "dall-e-3" def main() -> None: # Generate an image based on the prompt response = openai.images.generate(prompt=prompt, model=model) # Prints response containing a URL link to image print(response) if __name__ == "__main__": main() ================================================ FILE: examples/realtime/audio_util.py ================================================ from __future__ import annotations import io import base64 import asyncio import threading from typing import Callable, Awaitable import numpy as np import pyaudio import sounddevice as sd from pydub import AudioSegment from openai.resources.realtime.realtime import AsyncRealtimeConnection CHUNK_LENGTH_S = 0.05 # 100ms SAMPLE_RATE = 24000 FORMAT = pyaudio.paInt16 CHANNELS = 1 # pyright: reportUnknownMemberType=false, reportUnknownVariableType=false, reportUnknownArgumentType=false def audio_to_pcm16_base64(audio_bytes: bytes) -> bytes: # load the audio file from the byte stream audio = AudioSegment.from_file(io.BytesIO(audio_bytes)) print(f"Loaded audio: {audio.frame_rate=} {audio.channels=} {audio.sample_width=} {audio.frame_width=}") # resample to 24kHz mono pcm16 pcm_audio = audio.set_frame_rate(SAMPLE_RATE).set_channels(CHANNELS).set_sample_width(2).raw_data return pcm_audio class AudioPlayerAsync: def __init__(self): self.queue = [] self.lock = threading.Lock() self.stream = sd.OutputStream( callback=self.callback, samplerate=SAMPLE_RATE, channels=CHANNELS, dtype=np.int16, blocksize=int(CHUNK_LENGTH_S * SAMPLE_RATE), ) self.playing = False self._frame_count = 0 def callback(self, outdata, frames, time, status): # noqa with self.lock: data = np.empty(0, dtype=np.int16) # get next item from queue if there is still space in the buffer while len(data) < frames and len(self.queue) > 0: item = self.queue.pop(0) frames_needed = frames - len(data) data = np.concatenate((data, item[:frames_needed])) if len(item) > frames_needed: self.queue.insert(0, item[frames_needed:]) self._frame_count += len(data) # fill the rest of the frames with zeros if there is no more data if len(data) < frames: data = np.concatenate((data, np.zeros(frames - len(data), dtype=np.int16))) outdata[:] = data.reshape(-1, 1) def reset_frame_count(self): self._frame_count = 0 def get_frame_count(self): return self._frame_count def add_data(self, data: bytes): with self.lock: # bytes is pcm16 single channel audio data, convert to numpy array np_data = np.frombuffer(data, dtype=np.int16) self.queue.append(np_data) if not self.playing: self.start() def start(self): self.playing = True self.stream.start() def stop(self): self.playing = False self.stream.stop() with self.lock: self.queue = [] def terminate(self): self.stream.close() async def send_audio_worker_sounddevice( connection: AsyncRealtimeConnection, should_send: Callable[[], bool] | None = None, start_send: Callable[[], Awaitable[None]] | None = None, ): sent_audio = False device_info = sd.query_devices() print(device_info) read_size = int(SAMPLE_RATE * 0.02) stream = sd.InputStream( channels=CHANNELS, samplerate=SAMPLE_RATE, dtype="int16", ) stream.start() try: while True: if stream.read_available < read_size: await asyncio.sleep(0) continue data, _ = stream.read(read_size) if should_send() if should_send else True: if not sent_audio and start_send: await start_send() await connection.send( {"type": "input_audio_buffer.append", "audio": base64.b64encode(data).decode("utf-8")} ) sent_audio = True elif sent_audio: print("Done, triggering inference") await connection.send({"type": "input_audio_buffer.commit"}) await connection.send({"type": "response.create", "response": {}}) sent_audio = False await asyncio.sleep(0) except KeyboardInterrupt: pass finally: stream.stop() stream.close() ================================================ FILE: examples/realtime/azure_realtime.py ================================================ import os import asyncio from azure.identity.aio import DefaultAzureCredential, get_bearer_token_provider from openai import AsyncOpenAI # Azure OpenAI Realtime Docs # How-to: https://learn.microsoft.com/azure/ai-services/openai/how-to/realtime-audio # Supported models and API versions: https://learn.microsoft.com/azure/ai-services/openai/how-to/realtime-audio#supported-models # Entra ID auth: https://learn.microsoft.com/azure/ai-services/openai/how-to/managed-identity async def main() -> None: """The following example demonstrates how to configure Azure OpenAI to use the Realtime API. For an audio example, see push_to_talk_app.py and update the client and model parameter accordingly. When prompted for user input, type a message and hit enter to send it to the model. Enter "q" to quit the conversation. """ credential = DefaultAzureCredential() token_provider = get_bearer_token_provider(credential, "https://cognitiveservices.azure.com/.default") token = await token_provider() # The endpoint of your Azure OpenAI resource is required. You can set it in the AZURE_OPENAI_ENDPOINT # environment variable. # You can find it in the Microsoft Foundry portal in the Overview page of your Azure OpenAI resource. # Example: https://{your-resource}.openai.azure.com endpoint = os.environ["AZURE_OPENAI_ENDPOINT"] # The deployment name of the model you want to use is required. You can set it in the AZURE_OPENAI_DEPLOYMENT_NAME # environment variable. # You can find it in the Foundry portal in the "Models + endpoints" page of your Azure OpenAI resource. # Example: gpt-realtime deployment_name = os.environ["AZURE_OPENAI_DEPLOYMENT_NAME"] base_url = endpoint.replace("https://", "wss://").rstrip("/") + "/openai/v1" # The APIs are compatible with the OpenAI client library. # You can use the OpenAI client library to access the Azure OpenAI APIs. # Make sure to set the baseURL and apiKey to use the Azure OpenAI endpoint and token. client = AsyncOpenAI(websocket_base_url=base_url, api_key=token) async with client.realtime.connect( model=deployment_name, ) as connection: await connection.session.update( session={ "output_modalities": ["text"], "model": deployment_name, "type": "realtime", } ) while True: user_input = input("Enter a message: ") if user_input == "q": break await connection.conversation.item.create( item={ "type": "message", "role": "user", "content": [{"type": "input_text", "text": user_input}], } ) await connection.response.create() async for event in connection: if event.type == "response.output_text.delta": print(event.delta, flush=True, end="") elif event.type == "response.output_text.done": print() elif event.type == "response.done": break await credential.close() asyncio.run(main()) ================================================ FILE: examples/realtime/push_to_talk_app.py ================================================ #!/usr/bin/env uv run #################################################################### # Sample TUI app with a push to talk interface to the Realtime API # # If you have `uv` installed and the `OPENAI_API_KEY` # # environment variable set, you can run this example with just # # # # `./examples/realtime/push_to_talk_app.py` # # # # On Mac, you'll also need `brew install portaudio ffmpeg` # #################################################################### # # /// script # requires-python = ">=3.9" # dependencies = [ # "textual", # "numpy", # "pyaudio", # "pydub", # "sounddevice", # "openai[realtime]", # ] # # [tool.uv.sources] # openai = { path = "../../", editable = true } # /// from __future__ import annotations import base64 import asyncio from typing import Any, cast from typing_extensions import override from textual import events from audio_util import CHANNELS, SAMPLE_RATE, AudioPlayerAsync from textual.app import App, ComposeResult from textual.widgets import Button, Static, RichLog from textual.reactive import reactive from textual.containers import Container from openai import AsyncOpenAI from openai.types.realtime.session import Session from openai.resources.realtime.realtime import AsyncRealtimeConnection class SessionDisplay(Static): """A widget that shows the current session ID.""" session_id = reactive("") @override def render(self) -> str: return f"Session ID: {self.session_id}" if self.session_id else "Connecting..." class AudioStatusIndicator(Static): """A widget that shows the current audio recording status.""" is_recording = reactive(False) @override def render(self) -> str: status = ( "🔴 Recording... (Press K to stop)" if self.is_recording else "⚪ Press K to start recording (Q to quit)" ) return status class RealtimeApp(App[None]): CSS = """ Screen { background: #1a1b26; /* Dark blue-grey background */ } Container { border: double rgb(91, 164, 91); } Horizontal { width: 100%; } #input-container { height: 5; /* Explicit height for input container */ margin: 1 1; padding: 1 2; } Input { width: 80%; height: 3; /* Explicit height for input */ } Button { width: 20%; height: 3; /* Explicit height for button */ } #bottom-pane { width: 100%; height: 82%; /* Reduced to make room for session display */ border: round rgb(205, 133, 63); content-align: center middle; } #status-indicator { height: 3; content-align: center middle; background: #2a2b36; border: solid rgb(91, 164, 91); margin: 1 1; } #session-display { height: 3; content-align: center middle; background: #2a2b36; border: solid rgb(91, 164, 91); margin: 1 1; } Static { color: white; } """ client: AsyncOpenAI should_send_audio: asyncio.Event audio_player: AudioPlayerAsync last_audio_item_id: str | None connection: AsyncRealtimeConnection | None session: Session | None connected: asyncio.Event def __init__(self) -> None: super().__init__() self.connection = None self.session = None self.client = AsyncOpenAI() self.audio_player = AudioPlayerAsync() self.last_audio_item_id = None self.should_send_audio = asyncio.Event() self.connected = asyncio.Event() @override def compose(self) -> ComposeResult: """Create child widgets for the app.""" with Container(): yield SessionDisplay(id="session-display") yield AudioStatusIndicator(id="status-indicator") yield RichLog(id="bottom-pane", wrap=True, highlight=True, markup=True) async def on_mount(self) -> None: self.run_worker(self.handle_realtime_connection()) self.run_worker(self.send_mic_audio()) async def handle_realtime_connection(self) -> None: async with self.client.realtime.connect(model="gpt-realtime") as conn: self.connection = conn self.connected.set() # note: this is the default and can be omitted # if you want to manually handle VAD yourself, then set `'turn_detection': None` await conn.session.update( session={ "audio": { "input": {"turn_detection": {"type": "server_vad"}}, }, "model": "gpt-realtime", "type": "realtime", } ) acc_items: dict[str, Any] = {} async for event in conn: if event.type == "session.created": self.session = event.session session_display = self.query_one(SessionDisplay) assert event.session.id is not None session_display.session_id = event.session.id continue if event.type == "session.updated": self.session = event.session continue if event.type == "response.output_audio.delta": if event.item_id != self.last_audio_item_id: self.audio_player.reset_frame_count() self.last_audio_item_id = event.item_id bytes_data = base64.b64decode(event.delta) self.audio_player.add_data(bytes_data) continue if event.type == "response.output_audio_transcript.delta": try: text = acc_items[event.item_id] except KeyError: acc_items[event.item_id] = event.delta else: acc_items[event.item_id] = text + event.delta # Clear and update the entire content because RichLog otherwise treats each delta as a new line bottom_pane = self.query_one("#bottom-pane", RichLog) bottom_pane.clear() bottom_pane.write(acc_items[event.item_id]) continue async def _get_connection(self) -> AsyncRealtimeConnection: await self.connected.wait() assert self.connection is not None return self.connection async def send_mic_audio(self) -> None: import sounddevice as sd # type: ignore sent_audio = False device_info = sd.query_devices() print(device_info) read_size = int(SAMPLE_RATE * 0.02) stream = sd.InputStream( channels=CHANNELS, samplerate=SAMPLE_RATE, dtype="int16", ) stream.start() status_indicator = self.query_one(AudioStatusIndicator) try: while True: if stream.read_available < read_size: await asyncio.sleep(0) continue await self.should_send_audio.wait() status_indicator.is_recording = True data, _ = stream.read(read_size) connection = await self._get_connection() if not sent_audio: asyncio.create_task(connection.send({"type": "response.cancel"})) sent_audio = True await connection.input_audio_buffer.append(audio=base64.b64encode(cast(Any, data)).decode("utf-8")) await asyncio.sleep(0) except KeyboardInterrupt: pass finally: stream.stop() stream.close() async def on_key(self, event: events.Key) -> None: """Handle key press events.""" if event.key == "enter": self.query_one(Button).press() return if event.key == "q": self.exit() return if event.key == "k": status_indicator = self.query_one(AudioStatusIndicator) if status_indicator.is_recording: self.should_send_audio.clear() status_indicator.is_recording = False if self.session and self.session.turn_detection is None: # The default in the API is that the model will automatically detect when the user has # stopped talking and then start responding itself. # # However if we're in manual `turn_detection` mode then we need to # manually tell the model to commit the audio buffer and start responding. conn = await self._get_connection() await conn.input_audio_buffer.commit() await conn.response.create() else: self.should_send_audio.set() status_indicator.is_recording = True if __name__ == "__main__": app = RealtimeApp() app.run() ================================================ FILE: examples/realtime/realtime.py ================================================ #!/usr/bin/env rye run python import asyncio from openai import AsyncOpenAI # Azure OpenAI Realtime Docs # How-to: https://learn.microsoft.com/azure/ai-services/openai/how-to/realtime-audio # Supported models and API versions: https://learn.microsoft.com/azure/ai-services/openai/how-to/realtime-audio#supported-models # Entra ID auth: https://learn.microsoft.com/azure/ai-services/openai/how-to/managed-identity async def main() -> None: """The following example demonstrates how to configure OpenAI to use the Realtime API. For an audio example, see push_to_talk_app.py and update the client and model parameter accordingly. When prompted for user input, type a message and hit enter to send it to the model. Enter "q" to quit the conversation. """ client = AsyncOpenAI() async with client.realtime.connect( model="gpt-realtime", ) as connection: await connection.session.update( session={ "output_modalities": ["text"], "model": "gpt-realtime", "type": "realtime", } ) while True: user_input = input("Enter a message: ") if user_input == "q": break await connection.conversation.item.create( item={ "type": "message", "role": "user", "content": [{"type": "input_text", "text": user_input}], } ) await connection.response.create() async for event in connection: if event.type == "response.output_text.delta": print(event.delta, flush=True, end="") elif event.type == "response.output_text.done": print() elif event.type == "response.done": break asyncio.run(main()) ================================================ FILE: examples/responses/__init__.py ================================================ ================================================ FILE: examples/responses/background.py ================================================ from typing import List import rich from pydantic import BaseModel from openai import OpenAI class Step(BaseModel): explanation: str output: str class MathResponse(BaseModel): steps: List[Step] final_answer: str client = OpenAI() id = None with client.responses.create( input="solve 8x + 31 = 2", model="gpt-4o-2024-08-06", background=True, stream=True, ) as stream: for event in stream: if event.type == "response.created": id = event.response.id if "output_text" in event.type: rich.print(event) if event.sequence_number == 10: break print("Interrupted. Continuing...") assert id is not None with client.responses.retrieve( response_id=id, stream=True, starting_after=10, ) as stream: for event in stream: if "output_text" in event.type: rich.print(event) ================================================ FILE: examples/responses/background_async.py ================================================ import asyncio from typing import List import rich from pydantic import BaseModel from openai._client import AsyncOpenAI class Step(BaseModel): explanation: str output: str class MathResponse(BaseModel): steps: List[Step] final_answer: str async def main() -> None: client = AsyncOpenAI() id = None async with await client.responses.create( input="solve 8x + 31 = 2", model="gpt-4o-2024-08-06", background=True, stream=True, ) as stream: async for event in stream: if event.type == "response.created": id = event.response.id if "output_text" in event.type: rich.print(event) if event.sequence_number == 10: break print("Interrupted. Continuing...") assert id is not None async with await client.responses.retrieve( response_id=id, stream=True, starting_after=10, ) as stream: async for event in stream: if "output_text" in event.type: rich.print(event) if __name__ == "__main__": asyncio.run(main()) ================================================ FILE: examples/responses/background_streaming.py ================================================ #!/usr/bin/env -S rye run python from typing import List import rich from pydantic import BaseModel from openai import OpenAI class Step(BaseModel): explanation: str output: str class MathResponse(BaseModel): steps: List[Step] final_answer: str client = OpenAI() id = None with client.responses.stream( input="solve 8x + 31 = 2", model="gpt-4o-2024-08-06", text_format=MathResponse, background=True, ) as stream: for event in stream: if event.type == "response.created": id = event.response.id if "output_text" in event.type: rich.print(event) if event.sequence_number == 10: break print("Interrupted. Continuing...") assert id is not None with client.responses.stream( response_id=id, starting_after=10, text_format=MathResponse, ) as stream: for event in stream: if "output_text" in event.type: rich.print(event) rich.print(stream.get_final_response()) ================================================ FILE: examples/responses/background_streaming_async.py ================================================ import asyncio from typing import List import rich from pydantic import BaseModel from openai import AsyncOpenAI class Step(BaseModel): explanation: str output: str class MathResponse(BaseModel): steps: List[Step] final_answer: str async def main() -> None: client = AsyncOpenAI() id = None async with client.responses.stream( input="solve 8x + 31 = 2", model="gpt-4o-2024-08-06", text_format=MathResponse, background=True, ) as stream: async for event in stream: if event.type == "response.created": id = event.response.id if "output_text" in event.type: rich.print(event) if event.sequence_number == 10: break print("Interrupted. Continuing...") assert id is not None async with client.responses.stream( response_id=id, starting_after=10, text_format=MathResponse, ) as stream: async for event in stream: if "output_text" in event.type: rich.print(event) rich.print(stream.get_final_response()) if __name__ == "__main__": asyncio.run(main()) ================================================ FILE: examples/responses/streaming.py ================================================ from typing import List import rich from pydantic import BaseModel from openai import OpenAI class Step(BaseModel): explanation: str output: str class MathResponse(BaseModel): steps: List[Step] final_answer: str client = OpenAI() with client.responses.stream( input="solve 8x + 31 = 2", model="gpt-4o-2024-08-06", text_format=MathResponse, ) as stream: for event in stream: if "output_text" in event.type: rich.print(event) rich.print(stream.get_final_response()) ================================================ FILE: examples/responses/streaming_tools.py ================================================ from enum import Enum from typing import List, Union import rich from pydantic import BaseModel import openai from openai import OpenAI class Table(str, Enum): orders = "orders" customers = "customers" products = "products" class Column(str, Enum): id = "id" status = "status" expected_delivery_date = "expected_delivery_date" delivered_at = "delivered_at" shipped_at = "shipped_at" ordered_at = "ordered_at" canceled_at = "canceled_at" class Operator(str, Enum): eq = "=" gt = ">" lt = "<" le = "<=" ge = ">=" ne = "!=" class OrderBy(str, Enum): asc = "asc" desc = "desc" class DynamicValue(BaseModel): column_name: str class Condition(BaseModel): column: str operator: Operator value: Union[str, int, DynamicValue] class Query(BaseModel): table_name: Table columns: List[Column] conditions: List[Condition] order_by: OrderBy client = OpenAI() with client.responses.stream( model="gpt-4o-2024-08-06", input="look up all my orders in november of last year that were fulfilled but not delivered on time", tools=[ openai.pydantic_function_tool(Query), ], ) as stream: for event in stream: rich.print(event) ================================================ FILE: examples/responses/structured_outputs.py ================================================ from typing import List import rich from pydantic import BaseModel from openai import OpenAI class Step(BaseModel): explanation: str output: str class MathResponse(BaseModel): steps: List[Step] final_answer: str client = OpenAI() rsp = client.responses.parse( input="solve 8x + 31 = 2", model="gpt-4o-2024-08-06", text_format=MathResponse, ) for output in rsp.output: if output.type != "message": raise Exception("Unexpected non message") for item in output.content: if item.type != "output_text": raise Exception("unexpected output type") if not item.parsed: raise Exception("Could not parse response") rich.print(item.parsed) print("answer: ", item.parsed.final_answer) # or message = rsp.output[0] assert message.type == "message" text = message.content[0] assert text.type == "output_text" if not text.parsed: raise Exception("Could not parse response") rich.print(text.parsed) print("answer: ", text.parsed.final_answer) ================================================ FILE: examples/responses/structured_outputs_tools.py ================================================ from enum import Enum from typing import List, Union import rich from pydantic import BaseModel import openai from openai import OpenAI class Table(str, Enum): orders = "orders" customers = "customers" products = "products" class Column(str, Enum): id = "id" status = "status" expected_delivery_date = "expected_delivery_date" delivered_at = "delivered_at" shipped_at = "shipped_at" ordered_at = "ordered_at" canceled_at = "canceled_at" class Operator(str, Enum): eq = "=" gt = ">" lt = "<" le = "<=" ge = ">=" ne = "!=" class OrderBy(str, Enum): asc = "asc" desc = "desc" class DynamicValue(BaseModel): column_name: str class Condition(BaseModel): column: str operator: Operator value: Union[str, int, DynamicValue] class Query(BaseModel): table_name: Table columns: List[Column] conditions: List[Condition] order_by: OrderBy client = OpenAI() response = client.responses.parse( model="gpt-4o-2024-08-06", input="look up all my orders in november of last year that were fulfilled but not delivered on time", tools=[ openai.pydantic_function_tool(Query), ], ) rich.print(response) function_call = response.output[0] assert function_call.type == "function_call" assert isinstance(function_call.parsed_arguments, Query) print("table name:", function_call.parsed_arguments.table_name) ================================================ FILE: examples/responses/websocket.py ================================================ from __future__ import annotations import json import argparse from typing import TYPE_CHECKING, Dict, Union, Literal, Optional, TypedDict, NamedTuple, cast from openai import OpenAI from openai.types.responses import ( FunctionToolParam, ToolChoiceOptions, ResponseInputParam, ResponseFailedEvent, ResponseCompletedEvent, ResponseInputItemParam, ResponseIncompleteEvent, ToolChoiceFunctionParam, ) if TYPE_CHECKING: from openai.resources.responses.responses import ResponsesConnection ToolName = Literal["get_sku_inventory", "get_supplier_eta", "get_quality_alerts"] ToolChoice = Union[ToolChoiceOptions, ToolChoiceFunctionParam] class DemoTurn(TypedDict): tool_name: ToolName prompt: str class SKUArguments(TypedDict): sku: str class SKUInventoryOutput(TypedDict): sku: str warehouse: str on_hand_units: int reserved_units: int reorder_point: int safety_stock: int class SupplierShipment(TypedDict): shipment_id: str eta_date: str quantity: int risk: str class SupplierETAOutput(TypedDict): sku: str supplier_shipments: list[SupplierShipment] class QualityAlert(TypedDict): alert_id: str status: str severity: str summary: str class QualityAlertsOutput(TypedDict): sku: str alerts: list[QualityAlert] class FunctionCallOutputItem(TypedDict): type: Literal["function_call_output"] call_id: str output: str class FunctionCallRequest(NamedTuple): name: str arguments_json: str call_id: str class RunResponseResult(NamedTuple): text: str response_id: str function_calls: list[FunctionCallRequest] class RunTurnResult(NamedTuple): assistant_text: str response_id: str ToolOutput = Union[SKUInventoryOutput, SupplierETAOutput, QualityAlertsOutput] TOOLS: list[FunctionToolParam] = [ { "type": "function", "name": "get_sku_inventory", "description": "Return froge pond inventory details for a SKU.", "strict": True, "parameters": { "type": "object", "properties": { "sku": { "type": "string", "description": "Stock-keeping unit identifier, such as sku-froge-lily-pad-deluxe.", } }, "required": ["sku"], "additionalProperties": False, }, }, { "type": "function", "name": "get_supplier_eta", "description": "Return tadpole supplier restock ETA data for a SKU.", "strict": True, "parameters": { "type": "object", "properties": { "sku": { "type": "string", "description": "Stock-keeping unit identifier, such as sku-froge-lily-pad-deluxe.", } }, "required": ["sku"], "additionalProperties": False, }, }, { "type": "function", "name": "get_quality_alerts", "description": "Return recent froge quality alerts for a SKU.", "strict": True, "parameters": { "type": "object", "properties": { "sku": { "type": "string", "description": "Stock-keeping unit identifier, such as sku-froge-lily-pad-deluxe.", } }, "required": ["sku"], "additionalProperties": False, }, }, ] DEMO_TURNS: list[DemoTurn] = [ { "tool_name": "get_sku_inventory", "prompt": "Use get_sku_inventory for sku='sku-froge-lily-pad-deluxe' and summarize current pond stock health in one sentence.", }, { "tool_name": "get_supplier_eta", "prompt": "Now use get_supplier_eta for the same SKU and summarize restock ETA and tadpole shipment risk.", }, { "tool_name": "get_quality_alerts", "prompt": "Finally use get_quality_alerts for the same SKU and summarize unresolved froge quality concerns in one short paragraph.", }, ] BETA_HEADER_VALUE = "responses_websockets=2026-02-06" def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser( description=("Run a 3-turn Responses WebSocket demo with function calling and chained previous_response_id.") ) parser.add_argument("--model", default="gpt-5.2", help="Model used in the `response.create` payload.") parser.add_argument( "--use-beta-header", action="store_true", help=f"Include `OpenAI-Beta: {BETA_HEADER_VALUE}` for beta websocket behavior.", ) parser.add_argument( "--show-events", action="store_true", help="Print non-text event types while streaming.", ) parser.add_argument( "--show-tool-io", action="store_true", help="Print each tool call and tool output payload.", ) return parser.parse_args() def parse_tool_name(name: str) -> ToolName: if name not in {"get_sku_inventory", "get_supplier_eta", "get_quality_alerts"}: raise ValueError(f"Unsupported tool requested: {name}") return cast(ToolName, name) def parse_sku_arguments(raw_arguments: str) -> SKUArguments: parsed_raw = json.loads(raw_arguments) if not isinstance(parsed_raw, dict): raise ValueError(f"Tool arguments must be a JSON object: {raw_arguments}") parsed = cast(Dict[str, object], parsed_raw) sku_value = parsed.get("sku") if not isinstance(sku_value, str): raise ValueError(f"Tool arguments must include a string `sku`: {raw_arguments}") return {"sku": sku_value} def call_tool(name: ToolName, arguments: SKUArguments) -> ToolOutput: sku = arguments["sku"] if name == "get_sku_inventory": return { "sku": sku, "warehouse": "pond-west-1", "on_hand_units": 84, "reserved_units": 26, "reorder_point": 60, "safety_stock": 40, } if name == "get_supplier_eta": return { "sku": sku, "supplier_shipments": [ { "shipment_id": "frog_ship_2201", "eta_date": "2026-02-24", "quantity": 180, "risk": "low", }, { "shipment_id": "frog_ship_2205", "eta_date": "2026-03-03", "quantity": 220, "risk": "medium", }, ], } if name == "get_quality_alerts": return { "sku": sku, "alerts": [ { "alert_id": "frog_qa_781", "status": "open", "severity": "high", "summary": "Lily-pad coating chipping in lot LP-42", }, { "alert_id": "frog_qa_795", "status": "in_progress", "severity": "medium", "summary": "Pond-crate scuff rate above threshold", }, { "alert_id": "frog_qa_802", "status": "resolved", "severity": "low", "summary": "Froge label alignment issue corrected", }, ], } raise ValueError(f"Unknown tool: {name}") def run_response( *, connection: ResponsesConnection, model: str, previous_response_id: Optional[str], input_payload: Union[str, ResponseInputParam], tools: list[FunctionToolParam], tool_choice: ToolChoice, show_events: bool, ) -> RunResponseResult: connection.response.create( model=model, input=input_payload, stream=True, previous_response_id=previous_response_id, tools=tools, tool_choice=tool_choice, ) text_parts: list[str] = [] function_calls: list[FunctionCallRequest] = [] response_id: Optional[str] = None for event in connection: if event.type == "response.output_text.delta": text_parts.append(event.delta) continue if event.type == "response.output_item.done" and event.item.type == "function_call": function_calls.append( FunctionCallRequest( name=event.item.name, arguments_json=event.item.arguments, call_id=event.item.call_id, ) ) continue if getattr(event, "type", None) == "error": raise RuntimeError(f"WebSocket error event: {event!r}") if isinstance(event, (ResponseCompletedEvent, ResponseFailedEvent, ResponseIncompleteEvent)): response_id = event.response.id if not isinstance(event, ResponseCompletedEvent): raise RuntimeError(f"Response ended with {event.type} (id={response_id})") if show_events: print(f"[{event.type}]") break if getattr(event, "type", None) == "response.done": # Responses over WebSocket currently emit `response.done` as the final event. # The payload still includes `response.id`, which we use for chaining. event_response = getattr(event, "response", None) event_response_id: Optional[str] = None if isinstance(event_response, dict): event_response_dict = cast(Dict[str, object], event_response) raw_event_response_id = event_response_dict.get("id") if isinstance(raw_event_response_id, str): event_response_id = raw_event_response_id else: raw_event_response_id = getattr(event_response, "id", None) if isinstance(raw_event_response_id, str): event_response_id = raw_event_response_id if not isinstance(event_response_id, str): raise RuntimeError(f"response.done event did not include a valid response.id: {event!r}") response_id = event_response_id if show_events: print("[response.done]") break if show_events: print(f"[{event.type}]") if response_id is None: raise RuntimeError("No terminal response event received.") return RunResponseResult( text="".join(text_parts), response_id=response_id, function_calls=function_calls, ) def run_turn( *, connection: ResponsesConnection, model: str, previous_response_id: Optional[str], turn_prompt: str, forced_tool_name: ToolName, show_events: bool, show_tool_io: bool, ) -> RunTurnResult: accumulated_text_parts: list[str] = [] current_input: Union[str, ResponseInputParam] = turn_prompt current_tool_choice: ToolChoice = {"type": "function", "name": forced_tool_name} current_previous_response_id = previous_response_id while True: response_result = run_response( connection=connection, model=model, previous_response_id=current_previous_response_id, input_payload=current_input, tools=TOOLS, tool_choice=current_tool_choice, show_events=show_events, ) if response_result.text: accumulated_text_parts.append(response_result.text) current_previous_response_id = response_result.response_id if not response_result.function_calls: break tool_outputs: ResponseInputParam = [] for function_call in response_result.function_calls: tool_name = parse_tool_name(function_call.name) arguments = parse_sku_arguments(function_call.arguments_json) output_payload = call_tool(tool_name, arguments) if show_tool_io: print(f"[tool_call] {function_call.name}({function_call.arguments_json})") print(f"[tool_output] {json.dumps(output_payload)}") function_call_output: FunctionCallOutputItem = { "type": "function_call_output", "call_id": function_call.call_id, "output": json.dumps(output_payload), } tool_outputs.append(cast(ResponseInputItemParam, function_call_output)) current_input = tool_outputs current_tool_choice = "none" return RunTurnResult( assistant_text="".join(accumulated_text_parts).strip(), response_id=current_previous_response_id, ) def main() -> None: args = parse_args() client = OpenAI() extra_headers = {"OpenAI-Beta": BETA_HEADER_VALUE} if args.use_beta_header else {} with client.responses.connect(extra_headers=extra_headers) as connection: previous_response_id: Optional[str] = None for index, turn in enumerate(DEMO_TURNS, start=1): print(f"\n=== Turn {index} ===") print(f"User: {turn['prompt']}") turn_result = run_turn( connection=connection, model=args.model, previous_response_id=previous_response_id, turn_prompt=turn["prompt"], forced_tool_name=turn["tool_name"], show_events=args.show_events, show_tool_io=args.show_tool_io, ) previous_response_id = turn_result.response_id print(f"Assistant: {turn_result.assistant_text}") if __name__ == "__main__": main() ================================================ FILE: examples/responses_input_tokens.py ================================================ from typing import List from openai import OpenAI from openai.types.responses.tool_param import ToolParam from openai.types.responses.response_input_item_param import ResponseInputItemParam def main() -> None: client = OpenAI() tools: List[ToolParam] = [ { "type": "function", "name": "get_current_weather", "description": "Get current weather in a given location", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "City and state, e.g. San Francisco, CA", }, "unit": { "type": "string", "enum": ["c", "f"], "description": "Temperature unit to use", }, }, "required": ["location", "unit"], "additionalProperties": False, }, "strict": True, } ] input_items: List[ResponseInputItemParam] = [ { "type": "message", "role": "user", "content": [{"type": "input_text", "text": "What's the weather in San Francisco today?"}], } ] response = client.responses.input_tokens.count( model="gpt-5", instructions="You are a concise assistant.", input=input_items, tools=tools, tool_choice={"type": "function", "name": "get_current_weather"}, ) print(f"input tokens: {response.input_tokens}") if __name__ == "__main__": main() ================================================ FILE: examples/speech_to_text.py ================================================ #!/usr/bin/env rye run python import asyncio from openai import AsyncOpenAI from openai.helpers import Microphone # gets OPENAI_API_KEY from your environment variables openai = AsyncOpenAI() async def main() -> None: print("Recording for the next 10 seconds...") recording = await Microphone(timeout=10).record() print("Recording complete") transcription = await openai.audio.transcriptions.create( model="whisper-1", file=recording, ) print(transcription.text) if __name__ == "__main__": asyncio.run(main()) ================================================ FILE: examples/streaming.py ================================================ #!/usr/bin/env -S poetry run python import asyncio from openai import OpenAI, AsyncOpenAI # This script assumes you have the OPENAI_API_KEY environment variable set to a valid OpenAI API key. # # You can run this script from the root directory like so: # `python examples/streaming.py` def sync_main() -> None: client = OpenAI() response = client.completions.create( model="gpt-3.5-turbo-instruct", prompt="1,2,3,", max_tokens=5, temperature=0, stream=True, ) # You can manually control iteration over the response first = next(response) print(f"got response data: {first.to_json()}") # Or you could automatically iterate through all of data. # Note that the for loop will not exit until *all* of the data has been processed. for data in response: print(data.to_json()) async def async_main() -> None: client = AsyncOpenAI() response = await client.completions.create( model="gpt-3.5-turbo-instruct", prompt="1,2,3,", max_tokens=5, temperature=0, stream=True, ) # You can manually control iteration over the response. # In Python 3.10+ you can also use the `await anext(response)` builtin instead first = await response.__anext__() print(f"got response data: {first.to_json()}") # Or you could automatically iterate through all of data. # Note that the for loop will not exit until *all* of the data has been processed. async for data in response: print(data.to_json()) sync_main() asyncio.run(async_main()) ================================================ FILE: examples/text_to_speech.py ================================================ #!/usr/bin/env rye run python import time import asyncio from openai import AsyncOpenAI from openai.helpers import LocalAudioPlayer # gets OPENAI_API_KEY from your environment variables openai = AsyncOpenAI() async def main() -> None: start_time = time.time() async with openai.audio.speech.with_streaming_response.create( model="tts-1", voice="alloy", response_format="pcm", # similar to WAV, but without a header chunk at the start. input="""I see skies of blue and clouds of white The bright blessed days, the dark sacred nights And I think to myself What a wonderful world""", ) as response: print(f"Time to first byte: {int((time.time() - start_time) * 1000)}ms") await LocalAudioPlayer().play(response) print(f"Time to play: {int((time.time() - start_time) * 1000)}ms") if __name__ == "__main__": asyncio.run(main()) ================================================ FILE: examples/uploads.py ================================================ import sys from pathlib import Path import rich from openai import OpenAI # generate this file using `./generate_file.sh` file = Path("/tmp/big_test_file.txt") client = OpenAI() def from_disk() -> None: print("uploading file from disk") upload = client.uploads.upload_file_chunked( file=file, mime_type="txt", purpose="batch", ) rich.print(upload) def from_in_memory() -> None: print("uploading file from memory") # read the data into memory ourselves to simulate # it coming from somewhere else data = file.read_bytes() filename = "my_file.txt" upload = client.uploads.upload_file_chunked( file=data, filename=filename, bytes=len(data), mime_type="txt", purpose="batch", ) rich.print(upload) if "memory" in sys.argv: from_in_memory() else: from_disk() ================================================ FILE: examples/video.py ================================================ #!/usr/bin/env -S poetry run python import asyncio from openai import AsyncOpenAI client = AsyncOpenAI() async def main() -> None: video = await client.videos.create_and_poll( model="sora-2", prompt="A video of the words 'Thank you' in sparkling letters", ) if video.status == "completed": print("Video successfully completed: ", video) else: print("Video creation failed. Status: ", video.status) asyncio.run(main()) ================================================ FILE: helpers.md ================================================ # Structured Outputs Parsing Helpers The OpenAI API supports extracting JSON from the model with the `response_format` request param, for more details on the API, see [this guide](https://platform.openai.com/docs/guides/structured-outputs). The SDK provides a `client.chat.completions.parse()` method which is a wrapper over the `client.chat.completions.create()` that provides richer integrations with Python specific types & returns a `ParsedChatCompletion` object, which is a subclass of the standard `ChatCompletion` class. ## Auto-parsing response content with Pydantic models You can pass a pydantic model to the `.parse()` method and the SDK will automatically convert the model into a JSON schema, send it to the API and parse the response content back into the given model. ```py from typing import List from pydantic import BaseModel from openai import OpenAI class Step(BaseModel): explanation: str output: str class MathResponse(BaseModel): steps: List[Step] final_answer: str client = OpenAI() completion = client.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[ {"role": "system", "content": "You are a helpful math tutor."}, {"role": "user", "content": "solve 8x + 31 = 2"}, ], response_format=MathResponse, ) message = completion.choices[0].message if message.parsed: print(message.parsed.steps) print("answer: ", message.parsed.final_answer) else: print(message.refusal) ``` ## Auto-parsing function tool calls The `.parse()` method will also automatically parse `function` tool calls if: - You use the `openai.pydantic_function_tool()` helper method - You mark your tool schema with `"strict": True` For example: ```py from enum import Enum from typing import List, Union from pydantic import BaseModel import openai class Table(str, Enum): orders = "orders" customers = "customers" products = "products" class Column(str, Enum): id = "id" status = "status" expected_delivery_date = "expected_delivery_date" delivered_at = "delivered_at" shipped_at = "shipped_at" ordered_at = "ordered_at" canceled_at = "canceled_at" class Operator(str, Enum): eq = "=" gt = ">" lt = "<" le = "<=" ge = ">=" ne = "!=" class OrderBy(str, Enum): asc = "asc" desc = "desc" class DynamicValue(BaseModel): column_name: str class Condition(BaseModel): column: str operator: Operator value: Union[str, int, DynamicValue] class Query(BaseModel): table_name: Table columns: List[Column] conditions: List[Condition] order_by: OrderBy client = openai.OpenAI() completion = client.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[ { "role": "system", "content": "You are a helpful assistant. The current date is August 6, 2024. You help users query for the data they are looking for by calling the query function.", }, { "role": "user", "content": "look up all my orders in may of last year that were fulfilled but not delivered on time", }, ], tools=[ openai.pydantic_function_tool(Query), ], ) tool_call = (completion.choices[0].message.tool_calls or [])[0] print(tool_call.function) assert isinstance(tool_call.function.parsed_arguments, Query) print(tool_call.function.parsed_arguments.table_name) ``` ### Differences from `.create()` The `chat.completions.parse()` method imposes some additional restrictions on it's usage that `chat.completions.create()` does not. - If the completion completes with `finish_reason` set to `length` or `content_filter`, the `LengthFinishReasonError` / `ContentFilterFinishReasonError` errors will be raised. - Only strict function tools can be passed, e.g. `{'type': 'function', 'function': {..., 'strict': True}}` # Streaming Helpers OpenAI supports streaming responses when interacting with the [Chat Completion](#chat-completions-api) & [Assistant](#assistant-streaming-api) APIs. ## Chat Completions API The SDK provides a `.chat.completions.stream()` method that wraps the `.chat.completions.create(stream=True)` stream providing a more granular event API & automatic accumulation of each delta. It also supports all aforementioned [parsing helpers](#structured-outputs-parsing-helpers). Unlike `.create(stream=True)`, the `.stream()` method requires usage within a context manager to prevent accidental leakage of the response: ```py from openai import AsyncOpenAI client = AsyncOpenAI() async with client.chat.completions.stream( model='gpt-4o-2024-08-06', messages=[...], ) as stream: async for event in stream: if event.type == 'content.delta': print(event.content, flush=True, end='') ``` When the context manager is entered, a `ChatCompletionStream` / `AsyncChatCompletionStream` instance is returned which, like `.create(stream=True)` is an iterator in the sync client and an async iterator in the async client. The full list of events that are yielded by the iterator are outlined [below](#chat-completions-events). When the context manager exits, the response will be closed, however the `stream` instance is still available outside the context manager. ### Chat Completions Events These events allow you to track the progress of the chat completion generation, access partial results, and handle different aspects of the stream separately. Below is a list of the different event types you may encounter: #### ChunkEvent Emitted for every chunk received from the API. - `type`: `"chunk"` - `chunk`: The raw `ChatCompletionChunk` object received from the API - `snapshot`: The current accumulated state of the chat completion #### ContentDeltaEvent Emitted for every chunk containing new content. - `type`: `"content.delta"` - `delta`: The new content string received in this chunk - `snapshot`: The accumulated content so far - `parsed`: The partially parsed content (if applicable) #### ContentDoneEvent Emitted when the content generation is complete. May be fired multiple times if there are multiple choices. - `type`: `"content.done"` - `content`: The full generated content - `parsed`: The fully parsed content (if applicable) #### RefusalDeltaEvent Emitted when a chunk contains part of a content refusal. - `type`: `"refusal.delta"` - `delta`: The new refusal content string received in this chunk - `snapshot`: The accumulated refusal content string so far #### RefusalDoneEvent Emitted when the refusal content is complete. - `type`: `"refusal.done"` - `refusal`: The full refusal content #### FunctionToolCallArgumentsDeltaEvent Emitted when a chunk contains part of a function tool call's arguments. - `type`: `"tool_calls.function.arguments.delta"` - `name`: The name of the function being called - `index`: The index of the tool call - `arguments`: The accumulated raw JSON string of arguments - `parsed_arguments`: The partially parsed arguments object - `arguments_delta`: The new JSON string fragment received in this chunk #### FunctionToolCallArgumentsDoneEvent Emitted when a function tool call's arguments are complete. - `type`: `"tool_calls.function.arguments.done"` - `name`: The name of the function being called - `index`: The index of the tool call - `arguments`: The full raw JSON string of arguments - `parsed_arguments`: The fully parsed arguments object. If you used `openai.pydantic_function_tool()` this will be an instance of the given model. #### LogprobsContentDeltaEvent Emitted when a chunk contains new content [log probabilities](https://cookbook.openai.com/examples/using_logprobs). - `type`: `"logprobs.content.delta"` - `content`: A list of the new log probabilities received in this chunk - `snapshot`: A list of the accumulated log probabilities so far #### LogprobsContentDoneEvent Emitted when all content [log probabilities](https://cookbook.openai.com/examples/using_logprobs) have been received. - `type`: `"logprobs.content.done"` - `content`: The full list of token log probabilities for the content #### LogprobsRefusalDeltaEvent Emitted when a chunk contains new refusal [log probabilities](https://cookbook.openai.com/examples/using_logprobs). - `type`: `"logprobs.refusal.delta"` - `refusal`: A list of the new log probabilities received in this chunk - `snapshot`: A list of the accumulated log probabilities so far #### LogprobsRefusalDoneEvent Emitted when all refusal [log probabilities](https://cookbook.openai.com/examples/using_logprobs) have been received. - `type`: `"logprobs.refusal.done"` - `refusal`: The full list of token log probabilities for the refusal ### Chat Completions stream methods A handful of helper methods are provided on the stream class for additional convenience, **`.get_final_completion()`** Returns the accumulated `ParsedChatCompletion` object ```py async with client.chat.completions.stream(...) as stream: ... completion = await stream.get_final_completion() print(completion.choices[0].message) ``` **`.until_done()`** If you want to wait for the stream to complete, you can use the `.until_done()` method. ```py async with client.chat.completions.stream(...) as stream: await stream.until_done() # stream is now finished ``` ## Assistant Streaming API OpenAI supports streaming responses from Assistants. The SDK provides convenience wrappers around the API so you can subscribe to the types of events you are interested in as well as receive accumulated responses. More information can be found in the documentation: [Assistant Streaming](https://platform.openai.com/docs/assistants/overview?lang=python) #### An example of creating a run and subscribing to some events You can subscribe to events by creating an event handler class and overloading the relevant event handlers. ```python from typing_extensions import override from openai import AssistantEventHandler, OpenAI from openai.types.beta.threads import Text, TextDelta from openai.types.beta.threads.runs import ToolCall, ToolCallDelta client = openai.OpenAI() # First, we create a EventHandler class to define # how we want to handle the events in the response stream. class EventHandler(AssistantEventHandler): @override def on_text_created(self, text: Text) -> None: print(f"\nassistant > ", end="", flush=True) @override def on_text_delta(self, delta: TextDelta, snapshot: Text): print(delta.value, end="", flush=True) @override def on_tool_call_created(self, tool_call: ToolCall): print(f"\nassistant > {tool_call.type}\n", flush=True) @override def on_tool_call_delta(self, delta: ToolCallDelta, snapshot: ToolCall): if delta.type == "code_interpreter" and delta.code_interpreter: if delta.code_interpreter.input: print(delta.code_interpreter.input, end="", flush=True) if delta.code_interpreter.outputs: print(f"\n\noutput >", flush=True) for output in delta.code_interpreter.outputs: if output.type == "logs": print(f"\n{output.logs}", flush=True) # Then, we use the `stream` SDK helper # with the `EventHandler` class to create the Run # and stream the response. with client.beta.threads.runs.stream( thread_id="thread_id", assistant_id="assistant_id", event_handler=EventHandler(), ) as stream: stream.until_done() ``` #### An example of iterating over events You can also iterate over all the streamed events. ```python with client.beta.threads.runs.stream( thread_id=thread.id, assistant_id=assistant.id ) as stream: for event in stream: # Print the text from text delta events if event.event == "thread.message.delta" and event.data.delta.content: print(event.data.delta.content[0].text) ``` #### An example of iterating over text You can also iterate over just the text deltas received ```python with client.beta.threads.runs.stream( thread_id=thread.id, assistant_id=assistant.id ) as stream: for text in stream.text_deltas: print(text) ``` ### Creating Streams There are three helper methods for creating streams: ```python client.beta.threads.runs.stream() ``` This method can be used to start and stream the response to an existing run with an associated thread that is already populated with messages. ```python client.beta.threads.create_and_run_stream() ``` This method can be used to add a message to a thread, start a run and then stream the response. ```python client.beta.threads.runs.submit_tool_outputs_stream() ``` This method can be used to submit a tool output to a run waiting on the output and start a stream. ### Assistant Events The assistant API provides events you can subscribe to for the following events. ```python def on_event(self, event: AssistantStreamEvent) ``` This allows you to subscribe to all the possible raw events sent by the OpenAI streaming API. In many cases it will be more convenient to subscribe to a more specific set of events for your use case. More information on the types of events can be found here: [Events](https://platform.openai.com/docs/api-reference/assistants-streaming/events) ```python def on_run_step_created(self, run_step: RunStep) def on_run_step_delta(self, delta: RunStepDelta, snapshot: RunStep) def on_run_step_done(self, run_step: RunStep) ``` These events allow you to subscribe to the creation, delta and completion of a RunStep. For more information on how Runs and RunSteps work see the documentation [Runs and RunSteps](https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps) ```python def on_message_created(self, message: Message) def on_message_delta(self, delta: MessageDelta, snapshot: Message) def on_message_done(self, message: Message) ``` This allows you to subscribe to Message creation, delta and completion events. Messages can contain different types of content that can be sent from a model (and events are available for specific content types). For convenience, the delta event includes both the incremental update and an accumulated snapshot of the content. More information on messages can be found on in the documentation page [Message](https://platform.openai.com/docs/api-reference/messages/object). ```python def on_text_created(self, text: Text) def on_text_delta(self, delta: TextDelta, snapshot: Text) def on_text_done(self, text: Text) ``` These events allow you to subscribe to the creation, delta and completion of a Text content (a specific type of message). For convenience, the delta event includes both the incremental update and an accumulated snapshot of the content. ```python def on_image_file_done(self, image_file: ImageFile) ``` Image files are not sent incrementally so an event is provided for when a image file is available. ```python def on_tool_call_created(self, tool_call: ToolCall) def on_tool_call_delta(self, delta: ToolCallDelta, snapshot: ToolCall) def on_tool_call_done(self, tool_call: ToolCall) ``` These events allow you to subscribe to events for the creation, delta and completion of a ToolCall. More information on tools can be found here [Tools](https://platform.openai.com/docs/assistants/tools) ```python def on_end(self) ``` The last event send when a stream ends. ```python def on_timeout(self) ``` This event is triggered if the request times out. ```python def on_exception(self, exception: Exception) ``` This event is triggered if an exception occurs during streaming. ### Assistant Methods The assistant streaming object also provides a few methods for convenience: ```python def current_event() -> AssistantStreamEvent | None def current_run() -> Run | None def current_message_snapshot() -> Message | None def current_run_step_snapshot() -> RunStep | None ``` These methods are provided to allow you to access additional context from within event handlers. In many cases the handlers should include all the information you need for processing, but if additional context is required it can be accessed. Note: There is not always a relevant context in certain situations (these will be `None` in those cases). ```python def get_final_run(self) -> Run def get_final_run_steps(self) -> List[RunStep] def get_final_messages(self) -> List[Message] ``` These methods are provided for convenience to collect information at the end of a stream. Calling these events will trigger consumption of the stream until completion and then return the relevant accumulated objects. # Polling Helpers When interacting with the API some actions such as starting a Run and adding files to vector stores are asynchronous and take time to complete. The SDK includes helper functions which will poll the status until it reaches a terminal state and then return the resulting object. If an API method results in an action which could benefit from polling there will be a corresponding version of the method ending in `_and_poll`. All methods also allow you to set the polling frequency, how often the API is checked for an update, via a function argument (`poll_interval_ms`). The polling methods are: ```python client.beta.threads.create_and_run_poll(...) client.beta.threads.runs.create_and_poll(...) client.beta.threads.runs.submit_tool_outputs_and_poll(...) client.beta.vector_stores.files.upload_and_poll(...) client.beta.vector_stores.files.create_and_poll(...) client.beta.vector_stores.file_batches.create_and_poll(...) client.beta.vector_stores.file_batches.upload_and_poll(...) client.videos.create_and_poll(...) ``` ================================================ FILE: noxfile.py ================================================ import nox @nox.session(reuse_venv=True, name="test-pydantic-v1") def test_pydantic_v1(session: nox.Session) -> None: session.install("-r", "requirements-dev.lock") session.install("pydantic<2") session.run("pytest", "--showlocals", "--ignore=tests/functional", *session.posargs) ================================================ FILE: pyproject.toml ================================================ [project] name = "openai" version = "2.29.0" description = "The official Python library for the openai API" dynamic = ["readme"] license = "Apache-2.0" authors = [ { name = "OpenAI", email = "support@openai.com" }, ] dependencies = [ "httpx>=0.23.0, <1", "pydantic>=1.9.0, <3", "typing-extensions>=4.11, <5", "typing-extensions>=4.14, <5", "anyio>=3.5.0, <5", "distro>=1.7.0, <2", "sniffio", "tqdm > 4", "jiter>=0.10.0, <1", ] requires-python = ">= 3.9" classifiers = [ "Typing :: Typed", "Intended Audience :: Developers", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", "Operating System :: OS Independent", "Operating System :: POSIX", "Operating System :: MacOS", "Operating System :: POSIX :: Linux", "Operating System :: Microsoft :: Windows", "Topic :: Software Development :: Libraries :: Python Modules", "License :: OSI Approved :: Apache Software License" ] [project.urls] Homepage = "https://github.com/openai/openai-python" Repository = "https://github.com/openai/openai-python" [project.scripts] openai = "openai.cli:main" [project.optional-dependencies] aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.9"] realtime = ["websockets >= 13, < 16"] datalib = ["numpy >= 1", "pandas >= 1.2.3", "pandas-stubs >= 1.1.0.11"] voice_helpers = ["sounddevice>=0.5.1", "numpy>=2.0.2"] [tool.rye] managed = true # version pins are in requirements-dev.lock dev-dependencies = [ "pyright==1.1.399", "mypy==1.17", "respx", "pytest", "pytest-asyncio", "ruff", "time-machine", "nox", "dirty-equals>=0.6.0", "importlib-metadata>=6.7.0", "rich>=13.7.1", "inline-snapshot>=0.28.0", "azure-identity >=1.14.1", "types-tqdm > 4", "types-pyaudio > 0", "trio >=0.22.2", "nest_asyncio==1.6.0", "pytest-xdist>=3.6.1", "griffe>=1", ] [tool.rye.scripts] format = { chain = [ "format:ruff", "format:docs", "fix:ruff", # run formatting again to fix any inconsistencies when imports are stripped "format:ruff", ]} "format:docs" = "bash -c 'python scripts/utils/ruffen-docs.py README.md $(find . -type f -name api.md)'" "format:ruff" = "ruff format" "lint" = { chain = [ "check:ruff", "typecheck", "check:importable", ]} "check:ruff" = "ruff check ." "fix:ruff" = "ruff check --fix ." "check:importable" = "python -c 'import openai'" typecheck = { chain = [ "typecheck:pyright", "typecheck:mypy" ]} "typecheck:pyright" = "scripts/run-pyright" "typecheck:verify-types" = "pyright --verifytypes openai --ignoreexternal" "typecheck:mypy" = "mypy ." [build-system] requires = ["hatchling==1.26.3", "hatch-fancy-pypi-readme"] build-backend = "hatchling.build" [tool.hatch.build] include = [ "src/*" ] [tool.hatch.build.targets.wheel] packages = ["src/openai"] [tool.hatch.build.targets.sdist] # Basically everything except hidden files/directories (such as .github, .devcontainers, .python-version, etc) include = [ "/*.toml", "/*.json", "/*.lock", "/*.md", "/mypy.ini", "/noxfile.py", "bin/*", "examples/*", "src/*", "tests/*", ] [tool.hatch.metadata.hooks.fancy-pypi-readme] content-type = "text/markdown" [[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]] path = "README.md" [[tool.hatch.metadata.hooks.fancy-pypi-readme.substitutions]] # replace relative links with absolute links pattern = '\[(.+?)\]\(((?!https?://)\S+?)\)' replacement = '[\1](https://github.com/openai/openai-python/tree/main/\g<2>)' [tool.pytest.ini_options] testpaths = ["tests"] addopts = "--tb=short -n auto" xfail_strict = true asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "session" filterwarnings = [ "error" ] [tool.inline-snapshot] format-command="ruff format --stdin-filename {filename}" [tool.pyright] # this enables practically every flag given by pyright. # there are a couple of flags that are still disabled by # default in strict mode as they are experimental and niche. typeCheckingMode = "strict" pythonVersion = "3.9" exclude = [ "_dev", ".venv", ".nox", ".git", # uses inline `uv` script dependencies # which means it can't be type checked "examples/realtime/audio_util.py", "examples/realtime/push_to_talk_app.py" ] reportImplicitOverride = true reportOverlappingOverload = false reportImportCycles = false reportPrivateUsage = false [tool.mypy] pretty = true show_error_codes = true # Exclude _files.py because mypy isn't smart enough to apply # the correct type narrowing and as this is an internal module # it's fine to just use Pyright. # # We also exclude our `tests` as mypy doesn't always infer # types correctly and Pyright will still catch any type errors. # # realtime examples use inline `uv` script dependencies # which means it can't be type checked exclude = [ 'src/openai/_files.py', '_dev/.*.py', 'tests/.*', 'src/openai/_utils/_logs.py', 'examples/realtime/audio_util.py', 'examples/realtime/push_to_talk_app.py', ] strict_equality = true implicit_reexport = true check_untyped_defs = true no_implicit_optional = true warn_return_any = true warn_unreachable = true warn_unused_configs = true # Turn these options off as it could cause conflicts # with the Pyright options. warn_unused_ignores = false warn_redundant_casts = false disallow_any_generics = true disallow_untyped_defs = true disallow_untyped_calls = true disallow_subclassing_any = true disallow_incomplete_defs = true disallow_untyped_decorators = true cache_fine_grained = true # By default, mypy reports an error if you assign a value to the result # of a function call that doesn't return anything. We do this in our test # cases: # ``` # result = ... # assert result is None # ``` # Changing this codegen to make mypy happy would increase complexity # and would not be worth it. disable_error_code = "func-returns-value,overload-cannot-match" # https://github.com/python/mypy/issues/12162 [[tool.mypy.overrides]] module = "black.files.*" ignore_errors = true ignore_missing_imports = true [tool.ruff] line-length = 120 output-format = "grouped" target-version = "py38" [tool.ruff.format] docstring-code-format = true [tool.ruff.lint] select = [ # isort "I", # bugbear rules "B", # remove unused imports "F401", # check for missing future annotations "FA102", # bare except statements "E722", # unused arguments "ARG", # print statements "T201", "T203", # misuse of typing.TYPE_CHECKING "TC004", # import rules "TID251", ] ignore = [ # mutable defaults "B006", ] unfixable = [ # disable auto fix for print statements "T201", "T203", ] extend-safe-fixes = ["FA102"] [tool.ruff.lint.flake8-tidy-imports.banned-api] "functools.lru_cache".msg = "This function does not retain type information for the wrapped function's arguments; The `lru_cache` function from `_utils` should be used instead" [tool.ruff.lint.isort] length-sort = true length-sort-straight = true combine-as-imports = true extra-standard-library = ["typing_extensions"] known-first-party = ["openai", "tests"] [tool.ruff.lint.per-file-ignores] "bin/**.py" = ["T201", "T203"] "scripts/**.py" = ["T201", "T203"] "tests/**.py" = ["T201", "T203"] "examples/**.py" = ["T201", "T203"] ================================================ FILE: release-please-config.json ================================================ { "packages": { ".": {} }, "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json", "include-v-in-tag": true, "include-component-in-tag": false, "versioning": "prerelease", "prerelease": true, "bump-minor-pre-major": true, "bump-patch-for-minor-pre-major": false, "pull-request-header": "Automated Release PR", "pull-request-title-pattern": "release: ${version}", "changelog-sections": [ { "type": "feat", "section": "Features" }, { "type": "fix", "section": "Bug Fixes" }, { "type": "perf", "section": "Performance Improvements" }, { "type": "revert", "section": "Reverts" }, { "type": "chore", "section": "Chores" }, { "type": "docs", "section": "Documentation" }, { "type": "style", "section": "Styles" }, { "type": "refactor", "section": "Refactors" }, { "type": "test", "section": "Tests", "hidden": true }, { "type": "build", "section": "Build System" }, { "type": "ci", "section": "Continuous Integration", "hidden": true } ], "release-type": "python", "extra-files": [ "src/openai/_version.py" ] } ================================================ FILE: scripts/bootstrap ================================================ #!/usr/bin/env bash set -e cd "$(dirname "$0")/.." if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { echo -n "==> Install Homebrew dependencies? (y/N): " read -r response case "$response" in [yY][eE][sS]|[yY]) brew bundle ;; *) ;; esac echo } fi echo "==> Installing Python dependencies…" # experimental uv support makes installations significantly faster rye config --set-bool behavior.use-uv=true rye sync ================================================ FILE: scripts/detect-breaking-changes ================================================ #!/usr/bin/env bash set -e cd "$(dirname "$0")/.." echo "==> Detecting breaking changes" TEST_PATHS=( tests/api_resources tests/test_client.py tests/test_response.py tests/test_legacy_response.py ) for PATHSPEC in "${TEST_PATHS[@]}"; do # Try to check out previous versions of the test files # with the current SDK. git checkout "$1" -- "${PATHSPEC}" 2>/dev/null || true done # Instead of running the tests, use the linter to check if an # older test is no longer compatible with the latest SDK. PYRIGHT_PROJECT=scripts/pyrightconfig.breaking-changes.json ./scripts/lint ================================================ FILE: scripts/detect-breaking-changes.py ================================================ from __future__ import annotations import sys from typing import Iterator from pathlib import Path import rich import griffe from rich.text import Text from rich.style import Style def public_members(obj: griffe.Object | griffe.Alias) -> dict[str, griffe.Object | griffe.Alias]: if isinstance(obj, griffe.Alias): # ignore imports for now, they're technically part of the public API # but we don't have good preventative measures in place to prevent # changing them return {} return {name: value for name, value in obj.all_members.items() if not name.startswith("_")} def find_breaking_changes( new_obj: griffe.Object | griffe.Alias, old_obj: griffe.Object | griffe.Alias, *, path: list[str], ) -> Iterator[Text | str]: new_members = public_members(new_obj) old_members = public_members(old_obj) for name, old_member in old_members.items(): if isinstance(old_member, griffe.Alias) and len(path) > 2: # ignore imports in `/types/` for now, they're technically part of the public API # but we don't have good preventative measures in place to prevent changing them continue new_member = new_members.get(name) if new_member is None: cls_name = old_member.__class__.__name__ yield Text(f"({cls_name})", style=Style(color="rgb(119, 119, 119)")) yield from [" " for _ in range(10 - len(cls_name))] yield f" {'.'.join(path)}.{name}" yield "\n" continue yield from find_breaking_changes(new_member, old_member, path=[*path, name]) def main() -> None: try: against_ref = sys.argv[1] except IndexError as err: raise RuntimeError("You must specify a base ref to run breaking change detection against") from err package = griffe.load( "openai", search_paths=[Path(__file__).parent.parent.joinpath("src")], ) old_package = griffe.load_git( "openai", ref=against_ref, search_paths=["src"], ) assert isinstance(package, griffe.Module) assert isinstance(old_package, griffe.Module) output = list(find_breaking_changes(package, old_package, path=["openai"])) if output: rich.print(Text("Breaking changes detected!", style=Style(color="rgb(165, 79, 87)"))) rich.print() for text in output: rich.print(text, end="") sys.exit(1) main() ================================================ FILE: scripts/format ================================================ #!/usr/bin/env bash set -e cd "$(dirname "$0")/.." echo "==> Running formatters" rye run format ================================================ FILE: scripts/lint ================================================ #!/usr/bin/env bash set -e cd "$(dirname "$0")/.." if [ "$1" = "--fix" ]; then echo "==> Running lints with --fix" rye run fix:ruff else echo "==> Running lints" rye run lint fi echo "==> Making sure it imports" rye run python -c 'import openai' ================================================ FILE: scripts/mock ================================================ #!/usr/bin/env bash set -e cd "$(dirname "$0")/.." if [[ -n "$1" && "$1" != '--'* ]]; then URL="$1" shift else URL="$(grep 'openapi_spec_url' .stats.yml | cut -d' ' -f2)" fi # Check if the URL is empty if [ -z "$URL" ]; then echo "Error: No OpenAPI spec path/url provided or found in .stats.yml" exit 1 fi echo "==> Starting mock server with URL ${URL}" # Run prism mock on the given spec if [ "$1" == "--daemon" ]; then # Pre-install the package so the download doesn't eat into the startup timeout npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism --version npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & # Wait for server to come online (max 30s) echo -n "Waiting for server" attempts=0 while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do attempts=$((attempts + 1)) if [ "$attempts" -ge 300 ]; then echo echo "Timed out waiting for Prism server to start" cat .prism.log exit 1 fi echo -n "." sleep 0.1 done if grep -q "✖ fatal" ".prism.log"; then cat .prism.log exit 1 fi echo else npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" fi ================================================ FILE: scripts/pyrightconfig.breaking-changes.json ================================================ { "extends": "../pyproject.toml", "reportDeprecated": false } ================================================ FILE: scripts/run-pyright ================================================ #!/usr/bin/env bash set -euo pipefail cd "$(dirname "$0")/.." CONFIG=${PYRIGHT_PROJECT:-pyproject.toml} exec pyright -p "$CONFIG" "$@" ================================================ FILE: scripts/test ================================================ #!/usr/bin/env bash set -e cd "$(dirname "$0")/.." RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' NC='\033[0m' # No Color function prism_is_running() { curl --silent "http://localhost:4010" >/dev/null 2>&1 } kill_server_on_port() { pids=$(lsof -t -i tcp:"$1" || echo "") if [ "$pids" != "" ]; then kill "$pids" echo "Stopped $pids." fi } function is_overriding_api_base_url() { [ -n "$TEST_API_BASE_URL" ] } if ! is_overriding_api_base_url && ! prism_is_running ; then # When we exit this script, make sure to kill the background mock server process trap 'kill_server_on_port 4010' EXIT # Start the dev server ./scripts/mock --daemon fi if is_overriding_api_base_url ; then echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" echo elif ! prism_is_running ; then echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server" echo -e "running against your OpenAPI spec." echo echo -e "To run the server, pass in the path or url of your OpenAPI" echo -e "spec to the prism command:" echo echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}" echo exit 1 else echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" echo fi export DEFER_PYDANTIC_BUILD=false echo "==> Running tests" rye run pytest "$@" echo "==> Running Pydantic v1 tests" rye run nox -s test-pydantic-v1 -- "$@" ================================================ FILE: scripts/utils/ruffen-docs.py ================================================ # fork of https://github.com/asottile/blacken-docs adapted for ruff from __future__ import annotations import re import sys import argparse import textwrap import contextlib import subprocess from typing import Match, Optional, Sequence, Generator, NamedTuple, cast MD_RE = re.compile( r"(?P^(?P *)```\s*python\n)" r"(?P.*?)" r"(?P^(?P=indent)```\s*$)", re.DOTALL | re.MULTILINE, ) MD_PYCON_RE = re.compile( r"(?P^(?P *)```\s*pycon\n)" r"(?P.*?)" r"(?P^(?P=indent)```.*$)", re.DOTALL | re.MULTILINE, ) PYCON_PREFIX = ">>> " PYCON_CONTINUATION_PREFIX = "..." PYCON_CONTINUATION_RE = re.compile( rf"^{re.escape(PYCON_CONTINUATION_PREFIX)}( |$)", ) DEFAULT_LINE_LENGTH = 100 class CodeBlockError(NamedTuple): offset: int exc: Exception def format_str( src: str, ) -> tuple[str, Sequence[CodeBlockError]]: errors: list[CodeBlockError] = [] @contextlib.contextmanager def _collect_error(match: Match[str]) -> Generator[None, None, None]: try: yield except Exception as e: errors.append(CodeBlockError(match.start(), e)) def _md_match(match: Match[str]) -> str: code = textwrap.dedent(match["code"]) with _collect_error(match): code = format_code_block(code) code = textwrap.indent(code, match["indent"]) return f"{match['before']}{code}{match['after']}" def _pycon_match(match: Match[str]) -> str: code = "" fragment = cast(Optional[str], None) def finish_fragment() -> None: nonlocal code nonlocal fragment if fragment is not None: with _collect_error(match): fragment = format_code_block(fragment) fragment_lines = fragment.splitlines() code += f"{PYCON_PREFIX}{fragment_lines[0]}\n" for line in fragment_lines[1:]: # Skip blank lines to handle Black adding a blank above # functions within blocks. A blank line would end the REPL # continuation prompt. # # >>> if True: # ... def f(): # ... pass # ... if line: code += f"{PYCON_CONTINUATION_PREFIX} {line}\n" if fragment_lines[-1].startswith(" "): code += f"{PYCON_CONTINUATION_PREFIX}\n" fragment = None indentation = None for line in match["code"].splitlines(): orig_line, line = line, line.lstrip() if indentation is None and line: indentation = len(orig_line) - len(line) continuation_match = PYCON_CONTINUATION_RE.match(line) if continuation_match and fragment is not None: fragment += line[continuation_match.end() :] + "\n" else: finish_fragment() if line.startswith(PYCON_PREFIX): fragment = line[len(PYCON_PREFIX) :] + "\n" else: code += orig_line[indentation:] + "\n" finish_fragment() return code def _md_pycon_match(match: Match[str]) -> str: code = _pycon_match(match) code = textwrap.indent(code, match["indent"]) return f"{match['before']}{code}{match['after']}" src = MD_RE.sub(_md_match, src) src = MD_PYCON_RE.sub(_md_pycon_match, src) return src, errors def format_code_block(code: str) -> str: return subprocess.check_output( [ sys.executable, "-m", "ruff", "format", "--stdin-filename=script.py", f"--line-length={DEFAULT_LINE_LENGTH}", ], encoding="utf-8", input=code, ) def format_file( filename: str, skip_errors: bool, ) -> int: with open(filename, encoding="UTF-8") as f: contents = f.read() new_contents, errors = format_str(contents) for error in errors: lineno = contents[: error.offset].count("\n") + 1 print(f"{filename}:{lineno}: code block parse error {error.exc}") if errors and not skip_errors: return 1 if contents != new_contents: print(f"{filename}: Rewriting...") with open(filename, "w", encoding="UTF-8") as f: f.write(new_contents) return 0 else: return 0 def main(argv: Sequence[str] | None = None) -> int: parser = argparse.ArgumentParser() parser.add_argument( "-l", "--line-length", type=int, default=DEFAULT_LINE_LENGTH, ) parser.add_argument( "-S", "--skip-string-normalization", action="store_true", ) parser.add_argument("-E", "--skip-errors", action="store_true") parser.add_argument("filenames", nargs="*") args = parser.parse_args(argv) retv = 0 for filename in args.filenames: retv |= format_file(filename, skip_errors=args.skip_errors) return retv if __name__ == "__main__": raise SystemExit(main()) ================================================ FILE: scripts/utils/upload-artifact.sh ================================================ #!/usr/bin/env bash set -exuo pipefail FILENAME=$(basename dist/*.whl) RESPONSE=$(curl -X POST "$URL?filename=$FILENAME" \ -H "Authorization: Bearer $AUTH" \ -H "Content-Type: application/json") SIGNED_URL=$(echo "$RESPONSE" | jq -r '.url') if [[ "$SIGNED_URL" == "null" ]]; then echo -e "\033[31mFailed to get signed URL.\033[0m" exit 1 fi UPLOAD_RESPONSE=$(curl -v -X PUT \ -H "Content-Type: binary/octet-stream" \ --data-binary "@dist/$FILENAME" "$SIGNED_URL" 2>&1) if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then echo -e "\033[32mUploaded build to Stainless storage.\033[0m" echo -e "\033[32mInstallation: pip install 'https://pkg.stainless.com/s/openai-python/$SHA/$FILENAME'\033[0m" else echo -e "\033[31mFailed to upload artifact.\033[0m" exit 1 fi ================================================ FILE: src/openai/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os as _os import typing as _t from typing_extensions import override from . import types from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes, omit, not_given from ._utils import file_from_path from ._client import Client, OpenAI, Stream, Timeout, Transport, AsyncClient, AsyncOpenAI, AsyncStream, RequestOptions from ._models import BaseModel from ._version import __title__, __version__ from ._response import APIResponse as APIResponse, AsyncAPIResponse as AsyncAPIResponse from ._constants import DEFAULT_TIMEOUT, DEFAULT_MAX_RETRIES, DEFAULT_CONNECTION_LIMITS from ._exceptions import ( APIError, OpenAIError, ConflictError, NotFoundError, APIStatusError, RateLimitError, APITimeoutError, BadRequestError, APIConnectionError, AuthenticationError, InternalServerError, PermissionDeniedError, LengthFinishReasonError, UnprocessableEntityError, APIResponseValidationError, InvalidWebhookSignatureError, ContentFilterFinishReasonError, ) from ._base_client import DefaultHttpxClient, DefaultAioHttpClient, DefaultAsyncHttpxClient from ._utils._logs import setup_logging as _setup_logging from ._legacy_response import HttpxBinaryResponseContent as HttpxBinaryResponseContent __all__ = [ "types", "__version__", "__title__", "NoneType", "Transport", "ProxiesTypes", "NotGiven", "NOT_GIVEN", "not_given", "Omit", "omit", "OpenAIError", "APIError", "APIStatusError", "APITimeoutError", "APIConnectionError", "APIResponseValidationError", "BadRequestError", "AuthenticationError", "PermissionDeniedError", "NotFoundError", "ConflictError", "UnprocessableEntityError", "RateLimitError", "InternalServerError", "LengthFinishReasonError", "ContentFilterFinishReasonError", "InvalidWebhookSignatureError", "Timeout", "RequestOptions", "Client", "AsyncClient", "Stream", "AsyncStream", "OpenAI", "AsyncOpenAI", "file_from_path", "BaseModel", "DEFAULT_TIMEOUT", "DEFAULT_MAX_RETRIES", "DEFAULT_CONNECTION_LIMITS", "DefaultHttpxClient", "DefaultAsyncHttpxClient", "DefaultAioHttpClient", ] if not _t.TYPE_CHECKING: from ._utils._resources_proxy import resources as resources from .lib import azure as _azure, pydantic_function_tool as pydantic_function_tool from .version import VERSION as VERSION from .lib.azure import AzureOpenAI as AzureOpenAI, AsyncAzureOpenAI as AsyncAzureOpenAI from .lib._old_api import * from .lib.streaming import ( AssistantEventHandler as AssistantEventHandler, AsyncAssistantEventHandler as AsyncAssistantEventHandler, ) _setup_logging() # Update the __module__ attribute for exported symbols so that # error messages point to this module instead of the module # it was originally defined in, e.g. # openai._exceptions.NotFoundError -> openai.NotFoundError __locals = locals() for __name in __all__: if not __name.startswith("__"): try: __locals[__name].__module__ = "openai" except (TypeError, AttributeError): # Some of our exported symbols are builtins which we can't set attributes for. pass # ------ Module level client ------ import typing as _t import typing_extensions as _te import httpx as _httpx from ._base_client import DEFAULT_TIMEOUT, DEFAULT_MAX_RETRIES api_key: str | None = None organization: str | None = None project: str | None = None webhook_secret: str | None = None base_url: str | _httpx.URL | None = None timeout: float | Timeout | None = DEFAULT_TIMEOUT max_retries: int = DEFAULT_MAX_RETRIES default_headers: _t.Mapping[str, str] | None = None default_query: _t.Mapping[str, object] | None = None http_client: _httpx.Client | None = None _ApiType = _te.Literal["openai", "azure"] api_type: _ApiType | None = _t.cast(_ApiType, _os.environ.get("OPENAI_API_TYPE")) api_version: str | None = _os.environ.get("OPENAI_API_VERSION") azure_endpoint: str | None = _os.environ.get("AZURE_OPENAI_ENDPOINT") azure_ad_token: str | None = _os.environ.get("AZURE_OPENAI_AD_TOKEN") azure_ad_token_provider: _azure.AzureADTokenProvider | None = None class _ModuleClient(OpenAI): # Note: we have to use type: ignores here as overriding class members # with properties is technically unsafe but it is fine for our use case @property # type: ignore @override def api_key(self) -> str | None: return api_key @api_key.setter # type: ignore def api_key(self, value: str | None) -> None: # type: ignore global api_key api_key = value @property # type: ignore @override def organization(self) -> str | None: return organization @organization.setter # type: ignore def organization(self, value: str | None) -> None: # type: ignore global organization organization = value @property # type: ignore @override def project(self) -> str | None: return project @project.setter # type: ignore def project(self, value: str | None) -> None: # type: ignore global project project = value @property # type: ignore @override def webhook_secret(self) -> str | None: return webhook_secret @webhook_secret.setter # type: ignore def webhook_secret(self, value: str | None) -> None: # type: ignore global webhook_secret webhook_secret = value @property @override def base_url(self) -> _httpx.URL: if base_url is not None: return _httpx.URL(base_url) return super().base_url @base_url.setter def base_url(self, url: _httpx.URL | str) -> None: super().base_url = url # type: ignore[misc] @property # type: ignore @override def timeout(self) -> float | Timeout | None: return timeout @timeout.setter # type: ignore def timeout(self, value: float | Timeout | None) -> None: # type: ignore global timeout timeout = value @property # type: ignore @override def max_retries(self) -> int: return max_retries @max_retries.setter # type: ignore def max_retries(self, value: int) -> None: # type: ignore global max_retries max_retries = value @property # type: ignore @override def _custom_headers(self) -> _t.Mapping[str, str] | None: return default_headers @_custom_headers.setter # type: ignore def _custom_headers(self, value: _t.Mapping[str, str] | None) -> None: # type: ignore global default_headers default_headers = value @property # type: ignore @override def _custom_query(self) -> _t.Mapping[str, object] | None: return default_query @_custom_query.setter # type: ignore def _custom_query(self, value: _t.Mapping[str, object] | None) -> None: # type: ignore global default_query default_query = value @property # type: ignore @override def _client(self) -> _httpx.Client: return http_client or super()._client @_client.setter # type: ignore def _client(self, value: _httpx.Client) -> None: # type: ignore global http_client http_client = value class _AzureModuleClient(_ModuleClient, AzureOpenAI): # type: ignore ... class _AmbiguousModuleClientUsageError(OpenAIError): def __init__(self) -> None: super().__init__( "Ambiguous use of module client; please set `openai.api_type` or the `OPENAI_API_TYPE` environment variable to `openai` or `azure`" ) def _has_openai_credentials() -> bool: return _os.environ.get("OPENAI_API_KEY") is not None def _has_azure_credentials() -> bool: return azure_endpoint is not None or _os.environ.get("AZURE_OPENAI_API_KEY") is not None def _has_azure_ad_credentials() -> bool: return ( _os.environ.get("AZURE_OPENAI_AD_TOKEN") is not None or azure_ad_token is not None or azure_ad_token_provider is not None ) _client: OpenAI | None = None def _load_client() -> OpenAI: # type: ignore[reportUnusedFunction] global _client if _client is None: global api_type, azure_endpoint, azure_ad_token, api_version if azure_endpoint is None: azure_endpoint = _os.environ.get("AZURE_OPENAI_ENDPOINT") if azure_ad_token is None: azure_ad_token = _os.environ.get("AZURE_OPENAI_AD_TOKEN") if api_version is None: api_version = _os.environ.get("OPENAI_API_VERSION") if api_type is None: has_openai = _has_openai_credentials() has_azure = _has_azure_credentials() has_azure_ad = _has_azure_ad_credentials() if has_openai and (has_azure or has_azure_ad): raise _AmbiguousModuleClientUsageError() if (azure_ad_token is not None or azure_ad_token_provider is not None) and _os.environ.get( "AZURE_OPENAI_API_KEY" ) is not None: raise _AmbiguousModuleClientUsageError() if has_azure or has_azure_ad: api_type = "azure" else: api_type = "openai" if api_type == "azure": _client = _AzureModuleClient( # type: ignore api_version=api_version, azure_endpoint=azure_endpoint, api_key=api_key, azure_ad_token=azure_ad_token, azure_ad_token_provider=azure_ad_token_provider, organization=organization, base_url=base_url, timeout=timeout, max_retries=max_retries, default_headers=default_headers, default_query=default_query, http_client=http_client, ) return _client _client = _ModuleClient( api_key=api_key, organization=organization, project=project, webhook_secret=webhook_secret, base_url=base_url, timeout=timeout, max_retries=max_retries, default_headers=default_headers, default_query=default_query, http_client=http_client, ) return _client return _client def _reset_client() -> None: # type: ignore[reportUnusedFunction] global _client _client = None from ._module_client import ( beta as beta, chat as chat, audio as audio, evals as evals, files as files, images as images, models as models, skills as skills, videos as videos, batches as batches, uploads as uploads, realtime as realtime, webhooks as webhooks, responses as responses, containers as containers, embeddings as embeddings, completions as completions, fine_tuning as fine_tuning, moderations as moderations, conversations as conversations, vector_stores as vector_stores, ) ================================================ FILE: src/openai/__main__.py ================================================ from .cli import main main() ================================================ FILE: src/openai/_base_client.py ================================================ from __future__ import annotations import sys import json import time import uuid import email import asyncio import inspect import logging import platform import warnings import email.utils from types import TracebackType from random import random from typing import ( TYPE_CHECKING, Any, Dict, Type, Union, Generic, Mapping, TypeVar, Iterable, Iterator, Optional, Generator, AsyncIterator, cast, overload, ) from typing_extensions import Literal, override, get_origin import anyio import httpx import distro import pydantic from httpx import URL from pydantic import PrivateAttr from . import _exceptions from ._qs import Querystring from ._files import to_httpx_files, async_to_httpx_files from ._types import ( Body, Omit, Query, Headers, Timeout, NotGiven, ResponseT, AnyMapping, PostParser, BinaryTypes, RequestFiles, HttpxSendArgs, RequestOptions, AsyncBinaryTypes, HttpxRequestFiles, ModelBuilderProtocol, not_given, ) from ._utils import SensitiveHeadersFilter, is_dict, is_list, asyncify, is_given, lru_cache, is_mapping from ._compat import PYDANTIC_V1, model_copy, model_dump from ._models import GenericModel, FinalRequestOptions, validate_type, construct_type from ._response import ( APIResponse, BaseAPIResponse, AsyncAPIResponse, extract_response_type, ) from ._constants import ( DEFAULT_TIMEOUT, MAX_RETRY_DELAY, DEFAULT_MAX_RETRIES, INITIAL_RETRY_DELAY, RAW_RESPONSE_HEADER, OVERRIDE_CAST_TO_HEADER, DEFAULT_CONNECTION_LIMITS, ) from ._streaming import Stream, SSEDecoder, AsyncStream, SSEBytesDecoder from ._exceptions import ( APIStatusError, APITimeoutError, APIConnectionError, APIResponseValidationError, ) from ._utils._json import openapi_dumps from ._legacy_response import LegacyAPIResponse log: logging.Logger = logging.getLogger(__name__) log.addFilter(SensitiveHeadersFilter()) # TODO: make base page type vars covariant SyncPageT = TypeVar("SyncPageT", bound="BaseSyncPage[Any]") AsyncPageT = TypeVar("AsyncPageT", bound="BaseAsyncPage[Any]") _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) _StreamT = TypeVar("_StreamT", bound=Stream[Any]) _AsyncStreamT = TypeVar("_AsyncStreamT", bound=AsyncStream[Any]) if TYPE_CHECKING: from httpx._config import ( DEFAULT_TIMEOUT_CONFIG, # pyright: ignore[reportPrivateImportUsage] ) HTTPX_DEFAULT_TIMEOUT = DEFAULT_TIMEOUT_CONFIG else: try: from httpx._config import DEFAULT_TIMEOUT_CONFIG as HTTPX_DEFAULT_TIMEOUT except ImportError: # taken from https://github.com/encode/httpx/blob/3ba5fe0d7ac70222590e759c31442b1cab263791/httpx/_config.py#L366 HTTPX_DEFAULT_TIMEOUT = Timeout(5.0) class PageInfo: """Stores the necessary information to build the request to retrieve the next page. Either `url` or `params` must be set. """ url: URL | NotGiven params: Query | NotGiven json: Body | NotGiven @overload def __init__( self, *, url: URL, ) -> None: ... @overload def __init__( self, *, params: Query, ) -> None: ... @overload def __init__( self, *, json: Body, ) -> None: ... def __init__( self, *, url: URL | NotGiven = not_given, json: Body | NotGiven = not_given, params: Query | NotGiven = not_given, ) -> None: self.url = url self.json = json self.params = params @override def __repr__(self) -> str: if self.url: return f"{self.__class__.__name__}(url={self.url})" if self.json: return f"{self.__class__.__name__}(json={self.json})" return f"{self.__class__.__name__}(params={self.params})" class BasePage(GenericModel, Generic[_T]): """ Defines the core interface for pagination. Type Args: ModelT: The pydantic model that represents an item in the response. Methods: has_next_page(): Check if there is another page available next_page_info(): Get the necessary information to make a request for the next page """ _options: FinalRequestOptions = PrivateAttr() _model: Type[_T] = PrivateAttr() def has_next_page(self) -> bool: items = self._get_page_items() if not items: return False return self.next_page_info() is not None def next_page_info(self) -> Optional[PageInfo]: ... def _get_page_items(self) -> Iterable[_T]: # type: ignore[empty-body] ... def _params_from_url(self, url: URL) -> httpx.QueryParams: # TODO: do we have to preprocess params here? return httpx.QueryParams(cast(Any, self._options.params)).merge(url.params) def _info_to_options(self, info: PageInfo) -> FinalRequestOptions: options = model_copy(self._options) options._strip_raw_response_header() if not isinstance(info.params, NotGiven): options.params = {**options.params, **info.params} return options if not isinstance(info.url, NotGiven): params = self._params_from_url(info.url) url = info.url.copy_with(params=params) options.params = dict(url.params) options.url = str(url) return options if not isinstance(info.json, NotGiven): if not is_mapping(info.json): raise TypeError("Pagination is only supported with mappings") if not options.json_data: options.json_data = {**info.json} else: if not is_mapping(options.json_data): raise TypeError("Pagination is only supported with mappings") options.json_data = {**options.json_data, **info.json} return options raise ValueError("Unexpected PageInfo state") class BaseSyncPage(BasePage[_T], Generic[_T]): _client: SyncAPIClient = pydantic.PrivateAttr() def _set_private_attributes( self, client: SyncAPIClient, model: Type[_T], options: FinalRequestOptions, ) -> None: if (not PYDANTIC_V1) and getattr(self, "__pydantic_private__", None) is None: self.__pydantic_private__ = {} self._model = model self._client = client self._options = options # Pydantic uses a custom `__iter__` method to support casting BaseModels # to dictionaries. e.g. dict(model). # As we want to support `for item in page`, this is inherently incompatible # with the default pydantic behaviour. It is not possible to support both # use cases at once. Fortunately, this is not a big deal as all other pydantic # methods should continue to work as expected as there is an alternative method # to cast a model to a dictionary, model.dict(), which is used internally # by pydantic. def __iter__(self) -> Iterator[_T]: # type: ignore for page in self.iter_pages(): for item in page._get_page_items(): yield item def iter_pages(self: SyncPageT) -> Iterator[SyncPageT]: page = self while True: yield page if page.has_next_page(): page = page.get_next_page() else: return def get_next_page(self: SyncPageT) -> SyncPageT: info = self.next_page_info() if not info: raise RuntimeError( "No next page expected; please check `.has_next_page()` before calling `.get_next_page()`." ) options = self._info_to_options(info) return self._client._request_api_list(self._model, page=self.__class__, options=options) class AsyncPaginator(Generic[_T, AsyncPageT]): def __init__( self, client: AsyncAPIClient, options: FinalRequestOptions, page_cls: Type[AsyncPageT], model: Type[_T], ) -> None: self._model = model self._client = client self._options = options self._page_cls = page_cls def __await__(self) -> Generator[Any, None, AsyncPageT]: return self._get_page().__await__() async def _get_page(self) -> AsyncPageT: def _parser(resp: AsyncPageT) -> AsyncPageT: resp._set_private_attributes( model=self._model, options=self._options, client=self._client, ) return resp self._options.post_parser = _parser return await self._client.request(self._page_cls, self._options) async def __aiter__(self) -> AsyncIterator[_T]: # https://github.com/microsoft/pyright/issues/3464 page = cast( AsyncPageT, await self, # type: ignore ) async for item in page: yield item class BaseAsyncPage(BasePage[_T], Generic[_T]): _client: AsyncAPIClient = pydantic.PrivateAttr() def _set_private_attributes( self, model: Type[_T], client: AsyncAPIClient, options: FinalRequestOptions, ) -> None: if (not PYDANTIC_V1) and getattr(self, "__pydantic_private__", None) is None: self.__pydantic_private__ = {} self._model = model self._client = client self._options = options async def __aiter__(self) -> AsyncIterator[_T]: async for page in self.iter_pages(): for item in page._get_page_items(): yield item async def iter_pages(self: AsyncPageT) -> AsyncIterator[AsyncPageT]: page = self while True: yield page if page.has_next_page(): page = await page.get_next_page() else: return async def get_next_page(self: AsyncPageT) -> AsyncPageT: info = self.next_page_info() if not info: raise RuntimeError( "No next page expected; please check `.has_next_page()` before calling `.get_next_page()`." ) options = self._info_to_options(info) return await self._client._request_api_list(self._model, page=self.__class__, options=options) _HttpxClientT = TypeVar("_HttpxClientT", bound=Union[httpx.Client, httpx.AsyncClient]) _DefaultStreamT = TypeVar("_DefaultStreamT", bound=Union[Stream[Any], AsyncStream[Any]]) class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]): _client: _HttpxClientT _version: str _base_url: URL max_retries: int timeout: Union[float, Timeout, None] _strict_response_validation: bool _idempotency_header: str | None _default_stream_cls: type[_DefaultStreamT] | None = None def __init__( self, *, version: str, base_url: str | URL, _strict_response_validation: bool, max_retries: int = DEFAULT_MAX_RETRIES, timeout: float | Timeout | None = DEFAULT_TIMEOUT, custom_headers: Mapping[str, str] | None = None, custom_query: Mapping[str, object] | None = None, ) -> None: self._version = version self._base_url = self._enforce_trailing_slash(URL(base_url)) self.max_retries = max_retries self.timeout = timeout self._custom_headers = custom_headers or {} self._custom_query = custom_query or {} self._strict_response_validation = _strict_response_validation self._idempotency_header = None self._platform: Platform | None = None if max_retries is None: # pyright: ignore[reportUnnecessaryComparison] raise TypeError( "max_retries cannot be None. If you want to disable retries, pass `0`; if you want unlimited retries, pass `math.inf` or a very high number; if you want the default behavior, pass `openai.DEFAULT_MAX_RETRIES`" ) def _enforce_trailing_slash(self, url: URL) -> URL: if url.raw_path.endswith(b"/"): return url return url.copy_with(raw_path=url.raw_path + b"/") def _make_status_error_from_response( self, response: httpx.Response, ) -> APIStatusError: if response.is_closed and not response.is_stream_consumed: # We can't read the response body as it has been closed # before it was read. This can happen if an event hook # raises a status error. body = None err_msg = f"Error code: {response.status_code}" else: err_text = response.text.strip() body = err_text try: body = json.loads(err_text) err_msg = f"Error code: {response.status_code} - {body}" except Exception: err_msg = err_text or f"Error code: {response.status_code}" return self._make_status_error(err_msg, body=body, response=response) def _make_status_error( self, err_msg: str, *, body: object, response: httpx.Response, ) -> _exceptions.APIStatusError: raise NotImplementedError() def _build_headers(self, options: FinalRequestOptions, *, retries_taken: int = 0) -> httpx.Headers: custom_headers = options.headers or {} headers_dict = _merge_mappings(self.default_headers, custom_headers) self._validate_headers(headers_dict, custom_headers) # headers are case-insensitive while dictionaries are not. headers = httpx.Headers(headers_dict) idempotency_header = self._idempotency_header if idempotency_header and options.idempotency_key and idempotency_header not in headers: headers[idempotency_header] = options.idempotency_key # Don't set these headers if they were already set or removed by the caller. We check # `custom_headers`, which can contain `Omit()`, instead of `headers` to account for the removal case. lower_custom_headers = [header.lower() for header in custom_headers] if "x-stainless-retry-count" not in lower_custom_headers: headers["x-stainless-retry-count"] = str(retries_taken) if "x-stainless-read-timeout" not in lower_custom_headers: timeout = self.timeout if isinstance(options.timeout, NotGiven) else options.timeout if isinstance(timeout, Timeout): timeout = timeout.read if timeout is not None: headers["x-stainless-read-timeout"] = str(timeout) return headers def _prepare_url(self, url: str) -> URL: """ Merge a URL argument together with any 'base_url' on the client, to create the URL used for the outgoing request. """ # Copied from httpx's `_merge_url` method. merge_url = URL(url) if merge_url.is_relative_url: merge_raw_path = self.base_url.raw_path + merge_url.raw_path.lstrip(b"/") return self.base_url.copy_with(raw_path=merge_raw_path) return merge_url def _make_sse_decoder(self) -> SSEDecoder | SSEBytesDecoder: return SSEDecoder() def _build_request( self, options: FinalRequestOptions, *, retries_taken: int = 0, ) -> httpx.Request: if log.isEnabledFor(logging.DEBUG): log.debug( "Request options: %s", model_dump( options, exclude_unset=True, # Pydantic v1 can't dump every type we support in content, so we exclude it for now. exclude={ "content", } if PYDANTIC_V1 else {}, ), ) kwargs: dict[str, Any] = {} json_data = options.json_data if options.extra_json is not None: if json_data is None: json_data = cast(Body, options.extra_json) elif is_mapping(json_data): json_data = _merge_mappings(json_data, options.extra_json) else: raise RuntimeError(f"Unexpected JSON data type, {type(json_data)}, cannot merge with `extra_body`") headers = self._build_headers(options, retries_taken=retries_taken) params = _merge_mappings(self.default_query, options.params) content_type = headers.get("Content-Type") files = options.files # If the given Content-Type header is multipart/form-data then it # has to be removed so that httpx can generate the header with # additional information for us as it has to be in this form # for the server to be able to correctly parse the request: # multipart/form-data; boundary=---abc-- if content_type is not None and content_type.startswith("multipart/form-data"): if "boundary" not in content_type: # only remove the header if the boundary hasn't been explicitly set # as the caller doesn't want httpx to come up with their own boundary headers.pop("Content-Type") # As we are now sending multipart/form-data instead of application/json # we need to tell httpx to use it, https://www.python-httpx.org/advanced/clients/#multipart-file-encoding if json_data: if not is_dict(json_data): raise TypeError( f"Expected query input to be a dictionary for multipart requests but got {type(json_data)} instead." ) kwargs["data"] = self._serialize_multipartform(json_data) # httpx determines whether or not to send a "multipart/form-data" # request based on the truthiness of the "files" argument. # This gets around that issue by generating a dict value that # evaluates to true. # # https://github.com/encode/httpx/discussions/2399#discussioncomment-3814186 if not files: files = cast(HttpxRequestFiles, ForceMultipartDict()) prepared_url = self._prepare_url(options.url) if "_" in prepared_url.host: # work around https://github.com/encode/httpx/discussions/2880 kwargs["extensions"] = {"sni_hostname": prepared_url.host.replace("_", "-")} is_body_allowed = options.method.lower() != "get" if is_body_allowed: if options.content is not None and json_data is not None: raise TypeError("Passing both `content` and `json_data` is not supported") if options.content is not None and files is not None: raise TypeError("Passing both `content` and `files` is not supported") if options.content is not None: kwargs["content"] = options.content elif isinstance(json_data, bytes): kwargs["content"] = json_data elif not files: # Don't set content when JSON is sent as multipart/form-data, # since httpx's content param overrides other body arguments kwargs["content"] = openapi_dumps(json_data) if is_given(json_data) and json_data is not None else None kwargs["files"] = files else: headers.pop("Content-Type", None) kwargs.pop("data", None) # TODO: report this error to httpx return self._client.build_request( # pyright: ignore[reportUnknownMemberType] headers=headers, timeout=self.timeout if isinstance(options.timeout, NotGiven) else options.timeout, method=options.method, url=prepared_url, # the `Query` type that we use is incompatible with qs' # `Params` type as it needs to be typed as `Mapping[str, object]` # so that passing a `TypedDict` doesn't cause an error. # https://github.com/microsoft/pyright/issues/3526#event-6715453066 params=self.qs.stringify(cast(Mapping[str, Any], params)) if params else None, **kwargs, ) def _serialize_multipartform(self, data: Mapping[object, object]) -> dict[str, object]: items = self.qs.stringify_items( # TODO: type ignore is required as stringify_items is well typed but we can't be # well typed without heavy validation. data, # type: ignore array_format="brackets", ) serialized: dict[str, object] = {} for key, value in items: existing = serialized.get(key) if not existing: serialized[key] = value continue # If a value has already been set for this key then that # means we're sending data like `array[]=[1, 2, 3]` and we # need to tell httpx that we want to send multiple values with # the same key which is done by using a list or a tuple. # # Note: 2d arrays should never result in the same key at both # levels so it's safe to assume that if the value is a list, # it was because we changed it to be a list. if is_list(existing): existing.append(value) else: serialized[key] = [existing, value] return serialized def _maybe_override_cast_to(self, cast_to: type[ResponseT], options: FinalRequestOptions) -> type[ResponseT]: if not is_given(options.headers): return cast_to # make a copy of the headers so we don't mutate user-input headers = dict(options.headers) # we internally support defining a temporary header to override the # default `cast_to` type for use with `.with_raw_response` and `.with_streaming_response` # see _response.py for implementation details override_cast_to = headers.pop(OVERRIDE_CAST_TO_HEADER, not_given) if is_given(override_cast_to): options.headers = headers return cast(Type[ResponseT], override_cast_to) return cast_to def _should_stream_response_body(self, request: httpx.Request) -> bool: return request.headers.get(RAW_RESPONSE_HEADER) == "stream" # type: ignore[no-any-return] def _process_response_data( self, *, data: object, cast_to: type[ResponseT], response: httpx.Response, ) -> ResponseT: if data is None: return cast(ResponseT, None) if cast_to is object: return cast(ResponseT, data) try: if inspect.isclass(cast_to) and issubclass(cast_to, ModelBuilderProtocol): return cast(ResponseT, cast_to.build(response=response, data=data)) if self._strict_response_validation: return cast(ResponseT, validate_type(type_=cast_to, value=data)) return cast(ResponseT, construct_type(type_=cast_to, value=data)) except pydantic.ValidationError as err: raise APIResponseValidationError(response=response, body=data) from err @property def qs(self) -> Querystring: return Querystring() @property def custom_auth(self) -> httpx.Auth | None: return None @property def auth_headers(self) -> dict[str, str]: return {} @property def default_headers(self) -> dict[str, str | Omit]: return { "Accept": "application/json", "Content-Type": "application/json", "User-Agent": self.user_agent, **self.platform_headers(), **self.auth_headers, **self._custom_headers, } @property def default_query(self) -> dict[str, object]: return { **self._custom_query, } def _validate_headers( self, headers: Headers, # noqa: ARG002 custom_headers: Headers, # noqa: ARG002 ) -> None: """Validate the given default headers and custom headers. Does nothing by default. """ return @property def user_agent(self) -> str: return f"{self.__class__.__name__}/Python {self._version}" @property def base_url(self) -> URL: return self._base_url @base_url.setter def base_url(self, url: URL | str) -> None: self._base_url = self._enforce_trailing_slash(url if isinstance(url, URL) else URL(url)) def platform_headers(self) -> Dict[str, str]: # the actual implementation is in a separate `lru_cache` decorated # function because adding `lru_cache` to methods will leak memory # https://github.com/python/cpython/issues/88476 return platform_headers(self._version, platform=self._platform) def _parse_retry_after_header(self, response_headers: Optional[httpx.Headers] = None) -> float | None: """Returns a float of the number of seconds (not milliseconds) to wait after retrying, or None if unspecified. About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After See also https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After#syntax """ if response_headers is None: return None # First, try the non-standard `retry-after-ms` header for milliseconds, # which is more precise than integer-seconds `retry-after` try: retry_ms_header = response_headers.get("retry-after-ms", None) return float(retry_ms_header) / 1000 except (TypeError, ValueError): pass # Next, try parsing `retry-after` header as seconds (allowing nonstandard floats). retry_header = response_headers.get("retry-after") try: # note: the spec indicates that this should only ever be an integer # but if someone sends a float there's no reason for us to not respect it return float(retry_header) except (TypeError, ValueError): pass # Last, try parsing `retry-after` as a date. retry_date_tuple = email.utils.parsedate_tz(retry_header) if retry_date_tuple is None: return None retry_date = email.utils.mktime_tz(retry_date_tuple) return float(retry_date - time.time()) def _calculate_retry_timeout( self, remaining_retries: int, options: FinalRequestOptions, response_headers: Optional[httpx.Headers] = None, ) -> float: max_retries = options.get_max_retries(self.max_retries) # If the API asks us to wait a certain amount of time (and it's a reasonable amount), just do what it says. retry_after = self._parse_retry_after_header(response_headers) if retry_after is not None and 0 < retry_after <= 60: return retry_after # Also cap retry count to 1000 to avoid any potential overflows with `pow` nb_retries = min(max_retries - remaining_retries, 1000) # Apply exponential backoff, but not more than the max. sleep_seconds = min(INITIAL_RETRY_DELAY * pow(2.0, nb_retries), MAX_RETRY_DELAY) # Apply some jitter, plus-or-minus half a second. jitter = 1 - 0.25 * random() timeout = sleep_seconds * jitter return timeout if timeout >= 0 else 0 def _should_retry(self, response: httpx.Response) -> bool: # Note: this is not a standard header should_retry_header = response.headers.get("x-should-retry") # If the server explicitly says whether or not to retry, obey. if should_retry_header == "true": log.debug("Retrying as header `x-should-retry` is set to `true`") return True if should_retry_header == "false": log.debug("Not retrying as header `x-should-retry` is set to `false`") return False # Retry on request timeouts. if response.status_code == 408: log.debug("Retrying due to status code %i", response.status_code) return True # Retry on lock timeouts. if response.status_code == 409: log.debug("Retrying due to status code %i", response.status_code) return True # Retry on rate limits. if response.status_code == 429: log.debug("Retrying due to status code %i", response.status_code) return True # Retry internal errors. if response.status_code >= 500: log.debug("Retrying due to status code %i", response.status_code) return True log.debug("Not retrying") return False def _idempotency_key(self) -> str: return f"stainless-python-retry-{uuid.uuid4()}" class _DefaultHttpxClient(httpx.Client): def __init__(self, **kwargs: Any) -> None: kwargs.setdefault("timeout", DEFAULT_TIMEOUT) kwargs.setdefault("limits", DEFAULT_CONNECTION_LIMITS) kwargs.setdefault("follow_redirects", True) super().__init__(**kwargs) if TYPE_CHECKING: DefaultHttpxClient = httpx.Client """An alias to `httpx.Client` that provides the same defaults that this SDK uses internally. This is useful because overriding the `http_client` with your own instance of `httpx.Client` will result in httpx's defaults being used, not ours. """ else: DefaultHttpxClient = _DefaultHttpxClient class SyncHttpxClientWrapper(DefaultHttpxClient): def __del__(self) -> None: if self.is_closed: return try: self.close() except Exception: pass class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]): _client: httpx.Client _default_stream_cls: type[Stream[Any]] | None = None def __init__( self, *, version: str, base_url: str | URL, max_retries: int = DEFAULT_MAX_RETRIES, timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.Client | None = None, custom_headers: Mapping[str, str] | None = None, custom_query: Mapping[str, object] | None = None, _strict_response_validation: bool, ) -> None: if not is_given(timeout): # if the user passed in a custom http client with a non-default # timeout set then we use that timeout. # # note: there is an edge case here where the user passes in a client # where they've explicitly set the timeout to match the default timeout # as this check is structural, meaning that we'll think they didn't # pass in a timeout and will ignore it if http_client and http_client.timeout != HTTPX_DEFAULT_TIMEOUT: timeout = http_client.timeout else: timeout = DEFAULT_TIMEOUT if http_client is not None and not isinstance(http_client, httpx.Client): # pyright: ignore[reportUnnecessaryIsInstance] raise TypeError( f"Invalid `http_client` argument; Expected an instance of `httpx.Client` but got {type(http_client)}" ) super().__init__( version=version, # cast to a valid type because mypy doesn't understand our type narrowing timeout=cast(Timeout, timeout), base_url=base_url, max_retries=max_retries, custom_query=custom_query, custom_headers=custom_headers, _strict_response_validation=_strict_response_validation, ) self._client = http_client or SyncHttpxClientWrapper( base_url=base_url, # cast to a valid type because mypy doesn't understand our type narrowing timeout=cast(Timeout, timeout), ) def is_closed(self) -> bool: return self._client.is_closed def close(self) -> None: """Close the underlying HTTPX client. The client will *not* be usable after this. """ # If an error is thrown while constructing a client, self._client # may not be present if hasattr(self, "_client"): self._client.close() def __enter__(self: _T) -> _T: return self def __exit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None, ) -> None: self.close() def _prepare_options( self, options: FinalRequestOptions, # noqa: ARG002 ) -> FinalRequestOptions: """Hook for mutating the given options""" return options def _prepare_request( self, request: httpx.Request, # noqa: ARG002 ) -> None: """This method is used as a callback for mutating the `Request` object after it has been constructed. This is useful for cases where you want to add certain headers based off of the request properties, e.g. `url`, `method` etc. """ return None @overload def request( self, cast_to: Type[ResponseT], options: FinalRequestOptions, *, stream: Literal[True], stream_cls: Type[_StreamT], ) -> _StreamT: ... @overload def request( self, cast_to: Type[ResponseT], options: FinalRequestOptions, *, stream: Literal[False] = False, ) -> ResponseT: ... @overload def request( self, cast_to: Type[ResponseT], options: FinalRequestOptions, *, stream: bool = False, stream_cls: Type[_StreamT] | None = None, ) -> ResponseT | _StreamT: ... def request( self, cast_to: Type[ResponseT], options: FinalRequestOptions, *, stream: bool = False, stream_cls: type[_StreamT] | None = None, ) -> ResponseT | _StreamT: cast_to = self._maybe_override_cast_to(cast_to, options) # create a copy of the options we were given so that if the # options are mutated later & we then retry, the retries are # given the original options input_options = model_copy(options) if input_options.idempotency_key is None and input_options.method.lower() != "get": # ensure the idempotency key is reused between requests input_options.idempotency_key = self._idempotency_key() response: httpx.Response | None = None max_retries = input_options.get_max_retries(self.max_retries) retries_taken = 0 for retries_taken in range(max_retries + 1): options = model_copy(input_options) options = self._prepare_options(options) remaining_retries = max_retries - retries_taken request = self._build_request(options, retries_taken=retries_taken) self._prepare_request(request) kwargs: HttpxSendArgs = {} if self.custom_auth is not None: kwargs["auth"] = self.custom_auth if options.follow_redirects is not None: kwargs["follow_redirects"] = options.follow_redirects log.debug("Sending HTTP Request: %s %s", request.method, request.url) response = None try: response = self._client.send( request, stream=stream or self._should_stream_response_body(request=request), **kwargs, ) except httpx.TimeoutException as err: log.debug("Encountered httpx.TimeoutException", exc_info=True) if remaining_retries > 0: self._sleep_for_retry( retries_taken=retries_taken, max_retries=max_retries, options=input_options, response=None, ) continue log.debug("Raising timeout error") raise APITimeoutError(request=request) from err except Exception as err: log.debug("Encountered Exception", exc_info=True) if remaining_retries > 0: self._sleep_for_retry( retries_taken=retries_taken, max_retries=max_retries, options=input_options, response=None, ) continue log.debug("Raising connection error") raise APIConnectionError(request=request) from err log.debug( 'HTTP Response: %s %s "%i %s" %s', request.method, request.url, response.status_code, response.reason_phrase, response.headers, ) log.debug("request_id: %s", response.headers.get("x-request-id")) try: response.raise_for_status() except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code log.debug("Encountered httpx.HTTPStatusError", exc_info=True) if remaining_retries > 0 and self._should_retry(err.response): err.response.close() self._sleep_for_retry( retries_taken=retries_taken, max_retries=max_retries, options=input_options, response=response, ) continue # If the response is streamed then we need to explicitly read the response # to completion before attempting to access the response text. if not err.response.is_closed: err.response.read() log.debug("Re-raising status error") raise self._make_status_error_from_response(err.response) from None break assert response is not None, "could not resolve response (should never happen)" return self._process_response( cast_to=cast_to, options=options, response=response, stream=stream, stream_cls=stream_cls, retries_taken=retries_taken, ) def _sleep_for_retry( self, *, retries_taken: int, max_retries: int, options: FinalRequestOptions, response: httpx.Response | None ) -> None: remaining_retries = max_retries - retries_taken if remaining_retries == 1: log.debug("1 retry left") else: log.debug("%i retries left", remaining_retries) timeout = self._calculate_retry_timeout(remaining_retries, options, response.headers if response else None) log.info("Retrying request to %s in %f seconds", options.url, timeout) time.sleep(timeout) def _process_response( self, *, cast_to: Type[ResponseT], options: FinalRequestOptions, response: httpx.Response, stream: bool, stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None, retries_taken: int = 0, ) -> ResponseT: if response.request.headers.get(RAW_RESPONSE_HEADER) == "true": return cast( ResponseT, LegacyAPIResponse( raw=response, client=self, cast_to=cast_to, stream=stream, stream_cls=stream_cls, options=options, retries_taken=retries_taken, ), ) origin = get_origin(cast_to) or cast_to if ( inspect.isclass(origin) and issubclass(origin, BaseAPIResponse) # we only want to actually return the custom BaseAPIResponse class if we're # returning the raw response, or if we're not streaming SSE, as if we're streaming # SSE then `cast_to` doesn't actively reflect the type we need to parse into and (not stream or bool(response.request.headers.get(RAW_RESPONSE_HEADER))) ): if not issubclass(origin, APIResponse): raise TypeError(f"API Response types must subclass {APIResponse}; Received {origin}") response_cls = cast("type[BaseAPIResponse[Any]]", cast_to) return cast( ResponseT, response_cls( raw=response, client=self, cast_to=extract_response_type(response_cls), stream=stream, stream_cls=stream_cls, options=options, retries_taken=retries_taken, ), ) if cast_to == httpx.Response: return cast(ResponseT, response) api_response = APIResponse( raw=response, client=self, cast_to=cast("type[ResponseT]", cast_to), # pyright: ignore[reportUnnecessaryCast] stream=stream, stream_cls=stream_cls, options=options, retries_taken=retries_taken, ) if bool(response.request.headers.get(RAW_RESPONSE_HEADER)): return cast(ResponseT, api_response) return api_response.parse() def _request_api_list( self, model: Type[object], page: Type[SyncPageT], options: FinalRequestOptions, ) -> SyncPageT: def _parser(resp: SyncPageT) -> SyncPageT: resp._set_private_attributes( client=self, model=model, options=options, ) return resp options.post_parser = _parser return self.request(page, options, stream=False) @overload def get( self, path: str, *, cast_to: Type[ResponseT], options: RequestOptions = {}, stream: Literal[False] = False, ) -> ResponseT: ... @overload def get( self, path: str, *, cast_to: Type[ResponseT], options: RequestOptions = {}, stream: Literal[True], stream_cls: type[_StreamT], ) -> _StreamT: ... @overload def get( self, path: str, *, cast_to: Type[ResponseT], options: RequestOptions = {}, stream: bool, stream_cls: type[_StreamT] | None = None, ) -> ResponseT | _StreamT: ... def get( self, path: str, *, cast_to: Type[ResponseT], options: RequestOptions = {}, stream: bool = False, stream_cls: type[_StreamT] | None = None, ) -> ResponseT | _StreamT: opts = FinalRequestOptions.construct(method="get", url=path, **options) # cast is required because mypy complains about returning Any even though # it understands the type variables return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)) @overload def post( self, path: str, *, cast_to: Type[ResponseT], body: Body | None = None, content: BinaryTypes | None = None, options: RequestOptions = {}, files: RequestFiles | None = None, stream: Literal[False] = False, ) -> ResponseT: ... @overload def post( self, path: str, *, cast_to: Type[ResponseT], body: Body | None = None, content: BinaryTypes | None = None, options: RequestOptions = {}, files: RequestFiles | None = None, stream: Literal[True], stream_cls: type[_StreamT], ) -> _StreamT: ... @overload def post( self, path: str, *, cast_to: Type[ResponseT], body: Body | None = None, content: BinaryTypes | None = None, options: RequestOptions = {}, files: RequestFiles | None = None, stream: bool, stream_cls: type[_StreamT] | None = None, ) -> ResponseT | _StreamT: ... def post( self, path: str, *, cast_to: Type[ResponseT], body: Body | None = None, content: BinaryTypes | None = None, options: RequestOptions = {}, files: RequestFiles | None = None, stream: bool = False, stream_cls: type[_StreamT] | None = None, ) -> ResponseT | _StreamT: if body is not None and content is not None: raise TypeError("Passing both `body` and `content` is not supported") if files is not None and content is not None: raise TypeError("Passing both `files` and `content` is not supported") if isinstance(body, bytes): warnings.warn( "Passing raw bytes as `body` is deprecated and will be removed in a future version. " "Please pass raw bytes via the `content` parameter instead.", DeprecationWarning, stacklevel=2, ) opts = FinalRequestOptions.construct( method="post", url=path, json_data=body, content=content, files=to_httpx_files(files), **options ) return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)) def patch( self, path: str, *, cast_to: Type[ResponseT], body: Body | None = None, content: BinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: if body is not None and content is not None: raise TypeError("Passing both `body` and `content` is not supported") if files is not None and content is not None: raise TypeError("Passing both `files` and `content` is not supported") if isinstance(body, bytes): warnings.warn( "Passing raw bytes as `body` is deprecated and will be removed in a future version. " "Please pass raw bytes via the `content` parameter instead.", DeprecationWarning, stacklevel=2, ) opts = FinalRequestOptions.construct( method="patch", url=path, json_data=body, content=content, files=to_httpx_files(files), **options ) return self.request(cast_to, opts) def put( self, path: str, *, cast_to: Type[ResponseT], body: Body | None = None, content: BinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: if body is not None and content is not None: raise TypeError("Passing both `body` and `content` is not supported") if files is not None and content is not None: raise TypeError("Passing both `files` and `content` is not supported") if isinstance(body, bytes): warnings.warn( "Passing raw bytes as `body` is deprecated and will be removed in a future version. " "Please pass raw bytes via the `content` parameter instead.", DeprecationWarning, stacklevel=2, ) opts = FinalRequestOptions.construct( method="put", url=path, json_data=body, content=content, files=to_httpx_files(files), **options ) return self.request(cast_to, opts) def delete( self, path: str, *, cast_to: Type[ResponseT], body: Body | None = None, content: BinaryTypes | None = None, options: RequestOptions = {}, ) -> ResponseT: if body is not None and content is not None: raise TypeError("Passing both `body` and `content` is not supported") if isinstance(body, bytes): warnings.warn( "Passing raw bytes as `body` is deprecated and will be removed in a future version. " "Please pass raw bytes via the `content` parameter instead.", DeprecationWarning, stacklevel=2, ) opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, content=content, **options) return self.request(cast_to, opts) def get_api_list( self, path: str, *, model: Type[object], page: Type[SyncPageT], body: Body | None = None, options: RequestOptions = {}, method: str = "get", ) -> SyncPageT: opts = FinalRequestOptions.construct(method=method, url=path, json_data=body, **options) return self._request_api_list(model, page, opts) class _DefaultAsyncHttpxClient(httpx.AsyncClient): def __init__(self, **kwargs: Any) -> None: kwargs.setdefault("timeout", DEFAULT_TIMEOUT) kwargs.setdefault("limits", DEFAULT_CONNECTION_LIMITS) kwargs.setdefault("follow_redirects", True) super().__init__(**kwargs) try: import httpx_aiohttp except ImportError: class _DefaultAioHttpClient(httpx.AsyncClient): def __init__(self, **_kwargs: Any) -> None: raise RuntimeError("To use the aiohttp client you must have installed the package with the `aiohttp` extra") else: class _DefaultAioHttpClient(httpx_aiohttp.HttpxAiohttpClient): # type: ignore def __init__(self, **kwargs: Any) -> None: kwargs.setdefault("timeout", DEFAULT_TIMEOUT) kwargs.setdefault("limits", DEFAULT_CONNECTION_LIMITS) kwargs.setdefault("follow_redirects", True) super().__init__(**kwargs) if TYPE_CHECKING: DefaultAsyncHttpxClient = httpx.AsyncClient """An alias to `httpx.AsyncClient` that provides the same defaults that this SDK uses internally. This is useful because overriding the `http_client` with your own instance of `httpx.AsyncClient` will result in httpx's defaults being used, not ours. """ DefaultAioHttpClient = httpx.AsyncClient """An alias to `httpx.AsyncClient` that changes the default HTTP transport to `aiohttp`.""" else: DefaultAsyncHttpxClient = _DefaultAsyncHttpxClient DefaultAioHttpClient = _DefaultAioHttpClient class AsyncHttpxClientWrapper(DefaultAsyncHttpxClient): def __del__(self) -> None: if self.is_closed: return try: # TODO(someday): support non asyncio runtimes here asyncio.get_running_loop().create_task(self.aclose()) except Exception: pass class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]): _client: httpx.AsyncClient _default_stream_cls: type[AsyncStream[Any]] | None = None def __init__( self, *, version: str, base_url: str | URL, _strict_response_validation: bool, max_retries: int = DEFAULT_MAX_RETRIES, timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.AsyncClient | None = None, custom_headers: Mapping[str, str] | None = None, custom_query: Mapping[str, object] | None = None, ) -> None: if not is_given(timeout): # if the user passed in a custom http client with a non-default # timeout set then we use that timeout. # # note: there is an edge case here where the user passes in a client # where they've explicitly set the timeout to match the default timeout # as this check is structural, meaning that we'll think they didn't # pass in a timeout and will ignore it if http_client and http_client.timeout != HTTPX_DEFAULT_TIMEOUT: timeout = http_client.timeout else: timeout = DEFAULT_TIMEOUT if http_client is not None and not isinstance(http_client, httpx.AsyncClient): # pyright: ignore[reportUnnecessaryIsInstance] raise TypeError( f"Invalid `http_client` argument; Expected an instance of `httpx.AsyncClient` but got {type(http_client)}" ) super().__init__( version=version, base_url=base_url, # cast to a valid type because mypy doesn't understand our type narrowing timeout=cast(Timeout, timeout), max_retries=max_retries, custom_query=custom_query, custom_headers=custom_headers, _strict_response_validation=_strict_response_validation, ) self._client = http_client or AsyncHttpxClientWrapper( base_url=base_url, # cast to a valid type because mypy doesn't understand our type narrowing timeout=cast(Timeout, timeout), ) def is_closed(self) -> bool: return self._client.is_closed async def close(self) -> None: """Close the underlying HTTPX client. The client will *not* be usable after this. """ await self._client.aclose() async def __aenter__(self: _T) -> _T: return self async def __aexit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None, ) -> None: await self.close() async def _prepare_options( self, options: FinalRequestOptions, # noqa: ARG002 ) -> FinalRequestOptions: """Hook for mutating the given options""" return options async def _prepare_request( self, request: httpx.Request, # noqa: ARG002 ) -> None: """This method is used as a callback for mutating the `Request` object after it has been constructed. This is useful for cases where you want to add certain headers based off of the request properties, e.g. `url`, `method` etc. """ return None @overload async def request( self, cast_to: Type[ResponseT], options: FinalRequestOptions, *, stream: Literal[False] = False, ) -> ResponseT: ... @overload async def request( self, cast_to: Type[ResponseT], options: FinalRequestOptions, *, stream: Literal[True], stream_cls: type[_AsyncStreamT], ) -> _AsyncStreamT: ... @overload async def request( self, cast_to: Type[ResponseT], options: FinalRequestOptions, *, stream: bool, stream_cls: type[_AsyncStreamT] | None = None, ) -> ResponseT | _AsyncStreamT: ... async def request( self, cast_to: Type[ResponseT], options: FinalRequestOptions, *, stream: bool = False, stream_cls: type[_AsyncStreamT] | None = None, ) -> ResponseT | _AsyncStreamT: if self._platform is None: # `get_platform` can make blocking IO calls so we # execute it earlier while we are in an async context self._platform = await asyncify(get_platform)() cast_to = self._maybe_override_cast_to(cast_to, options) # create a copy of the options we were given so that if the # options are mutated later & we then retry, the retries are # given the original options input_options = model_copy(options) if input_options.idempotency_key is None and input_options.method.lower() != "get": # ensure the idempotency key is reused between requests input_options.idempotency_key = self._idempotency_key() response: httpx.Response | None = None max_retries = input_options.get_max_retries(self.max_retries) retries_taken = 0 for retries_taken in range(max_retries + 1): options = model_copy(input_options) options = await self._prepare_options(options) remaining_retries = max_retries - retries_taken request = self._build_request(options, retries_taken=retries_taken) await self._prepare_request(request) kwargs: HttpxSendArgs = {} if self.custom_auth is not None: kwargs["auth"] = self.custom_auth if options.follow_redirects is not None: kwargs["follow_redirects"] = options.follow_redirects log.debug("Sending HTTP Request: %s %s", request.method, request.url) response = None try: response = await self._client.send( request, stream=stream or self._should_stream_response_body(request=request), **kwargs, ) except httpx.TimeoutException as err: log.debug("Encountered httpx.TimeoutException", exc_info=True) if remaining_retries > 0: await self._sleep_for_retry( retries_taken=retries_taken, max_retries=max_retries, options=input_options, response=None, ) continue log.debug("Raising timeout error") raise APITimeoutError(request=request) from err except Exception as err: log.debug("Encountered Exception", exc_info=True) if remaining_retries > 0: await self._sleep_for_retry( retries_taken=retries_taken, max_retries=max_retries, options=input_options, response=None, ) continue log.debug("Raising connection error") raise APIConnectionError(request=request) from err log.debug( 'HTTP Response: %s %s "%i %s" %s', request.method, request.url, response.status_code, response.reason_phrase, response.headers, ) log.debug("request_id: %s", response.headers.get("x-request-id")) try: response.raise_for_status() except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code log.debug("Encountered httpx.HTTPStatusError", exc_info=True) if remaining_retries > 0 and self._should_retry(err.response): await err.response.aclose() await self._sleep_for_retry( retries_taken=retries_taken, max_retries=max_retries, options=input_options, response=response, ) continue # If the response is streamed then we need to explicitly read the response # to completion before attempting to access the response text. if not err.response.is_closed: await err.response.aread() log.debug("Re-raising status error") raise self._make_status_error_from_response(err.response) from None break assert response is not None, "could not resolve response (should never happen)" return await self._process_response( cast_to=cast_to, options=options, response=response, stream=stream, stream_cls=stream_cls, retries_taken=retries_taken, ) async def _sleep_for_retry( self, *, retries_taken: int, max_retries: int, options: FinalRequestOptions, response: httpx.Response | None ) -> None: remaining_retries = max_retries - retries_taken if remaining_retries == 1: log.debug("1 retry left") else: log.debug("%i retries left", remaining_retries) timeout = self._calculate_retry_timeout(remaining_retries, options, response.headers if response else None) log.info("Retrying request to %s in %f seconds", options.url, timeout) await anyio.sleep(timeout) async def _process_response( self, *, cast_to: Type[ResponseT], options: FinalRequestOptions, response: httpx.Response, stream: bool, stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None, retries_taken: int = 0, ) -> ResponseT: if response.request.headers.get(RAW_RESPONSE_HEADER) == "true": return cast( ResponseT, LegacyAPIResponse( raw=response, client=self, cast_to=cast_to, stream=stream, stream_cls=stream_cls, options=options, retries_taken=retries_taken, ), ) origin = get_origin(cast_to) or cast_to if ( inspect.isclass(origin) and issubclass(origin, BaseAPIResponse) # we only want to actually return the custom BaseAPIResponse class if we're # returning the raw response, or if we're not streaming SSE, as if we're streaming # SSE then `cast_to` doesn't actively reflect the type we need to parse into and (not stream or bool(response.request.headers.get(RAW_RESPONSE_HEADER))) ): if not issubclass(origin, AsyncAPIResponse): raise TypeError(f"API Response types must subclass {AsyncAPIResponse}; Received {origin}") response_cls = cast("type[BaseAPIResponse[Any]]", cast_to) return cast( "ResponseT", response_cls( raw=response, client=self, cast_to=extract_response_type(response_cls), stream=stream, stream_cls=stream_cls, options=options, retries_taken=retries_taken, ), ) if cast_to == httpx.Response: return cast(ResponseT, response) api_response = AsyncAPIResponse( raw=response, client=self, cast_to=cast("type[ResponseT]", cast_to), # pyright: ignore[reportUnnecessaryCast] stream=stream, stream_cls=stream_cls, options=options, retries_taken=retries_taken, ) if bool(response.request.headers.get(RAW_RESPONSE_HEADER)): return cast(ResponseT, api_response) return await api_response.parse() def _request_api_list( self, model: Type[_T], page: Type[AsyncPageT], options: FinalRequestOptions, ) -> AsyncPaginator[_T, AsyncPageT]: return AsyncPaginator(client=self, options=options, page_cls=page, model=model) @overload async def get( self, path: str, *, cast_to: Type[ResponseT], options: RequestOptions = {}, stream: Literal[False] = False, ) -> ResponseT: ... @overload async def get( self, path: str, *, cast_to: Type[ResponseT], options: RequestOptions = {}, stream: Literal[True], stream_cls: type[_AsyncStreamT], ) -> _AsyncStreamT: ... @overload async def get( self, path: str, *, cast_to: Type[ResponseT], options: RequestOptions = {}, stream: bool, stream_cls: type[_AsyncStreamT] | None = None, ) -> ResponseT | _AsyncStreamT: ... async def get( self, path: str, *, cast_to: Type[ResponseT], options: RequestOptions = {}, stream: bool = False, stream_cls: type[_AsyncStreamT] | None = None, ) -> ResponseT | _AsyncStreamT: opts = FinalRequestOptions.construct(method="get", url=path, **options) return await self.request(cast_to, opts, stream=stream, stream_cls=stream_cls) @overload async def post( self, path: str, *, cast_to: Type[ResponseT], body: Body | None = None, content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, stream: Literal[False] = False, ) -> ResponseT: ... @overload async def post( self, path: str, *, cast_to: Type[ResponseT], body: Body | None = None, content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, stream: Literal[True], stream_cls: type[_AsyncStreamT], ) -> _AsyncStreamT: ... @overload async def post( self, path: str, *, cast_to: Type[ResponseT], body: Body | None = None, content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, stream: bool, stream_cls: type[_AsyncStreamT] | None = None, ) -> ResponseT | _AsyncStreamT: ... async def post( self, path: str, *, cast_to: Type[ResponseT], body: Body | None = None, content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, stream: bool = False, stream_cls: type[_AsyncStreamT] | None = None, ) -> ResponseT | _AsyncStreamT: if body is not None and content is not None: raise TypeError("Passing both `body` and `content` is not supported") if files is not None and content is not None: raise TypeError("Passing both `files` and `content` is not supported") if isinstance(body, bytes): warnings.warn( "Passing raw bytes as `body` is deprecated and will be removed in a future version. " "Please pass raw bytes via the `content` parameter instead.", DeprecationWarning, stacklevel=2, ) opts = FinalRequestOptions.construct( method="post", url=path, json_data=body, content=content, files=await async_to_httpx_files(files), **options ) return await self.request(cast_to, opts, stream=stream, stream_cls=stream_cls) async def patch( self, path: str, *, cast_to: Type[ResponseT], body: Body | None = None, content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: if body is not None and content is not None: raise TypeError("Passing both `body` and `content` is not supported") if files is not None and content is not None: raise TypeError("Passing both `files` and `content` is not supported") if isinstance(body, bytes): warnings.warn( "Passing raw bytes as `body` is deprecated and will be removed in a future version. " "Please pass raw bytes via the `content` parameter instead.", DeprecationWarning, stacklevel=2, ) opts = FinalRequestOptions.construct( method="patch", url=path, json_data=body, content=content, files=await async_to_httpx_files(files), **options, ) return await self.request(cast_to, opts) async def put( self, path: str, *, cast_to: Type[ResponseT], body: Body | None = None, content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: if body is not None and content is not None: raise TypeError("Passing both `body` and `content` is not supported") if files is not None and content is not None: raise TypeError("Passing both `files` and `content` is not supported") if isinstance(body, bytes): warnings.warn( "Passing raw bytes as `body` is deprecated and will be removed in a future version. " "Please pass raw bytes via the `content` parameter instead.", DeprecationWarning, stacklevel=2, ) opts = FinalRequestOptions.construct( method="put", url=path, json_data=body, content=content, files=await async_to_httpx_files(files), **options ) return await self.request(cast_to, opts) async def delete( self, path: str, *, cast_to: Type[ResponseT], body: Body | None = None, content: AsyncBinaryTypes | None = None, options: RequestOptions = {}, ) -> ResponseT: if body is not None and content is not None: raise TypeError("Passing both `body` and `content` is not supported") if isinstance(body, bytes): warnings.warn( "Passing raw bytes as `body` is deprecated and will be removed in a future version. " "Please pass raw bytes via the `content` parameter instead.", DeprecationWarning, stacklevel=2, ) opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, content=content, **options) return await self.request(cast_to, opts) def get_api_list( self, path: str, *, model: Type[_T], page: Type[AsyncPageT], body: Body | None = None, options: RequestOptions = {}, method: str = "get", ) -> AsyncPaginator[_T, AsyncPageT]: opts = FinalRequestOptions.construct(method=method, url=path, json_data=body, **options) return self._request_api_list(model, page, opts) def make_request_options( *, query: Query | None = None, extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, idempotency_key: str | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, post_parser: PostParser | NotGiven = not_given, synthesize_event_and_data: bool | None = None, ) -> RequestOptions: """Create a dict of type RequestOptions without keys of NotGiven values.""" options: RequestOptions = {} if extra_headers is not None: options["headers"] = extra_headers if extra_body is not None: options["extra_json"] = cast(AnyMapping, extra_body) if query is not None: options["params"] = query if extra_query is not None: options["params"] = {**options.get("params", {}), **extra_query} if not isinstance(timeout, NotGiven): options["timeout"] = timeout if idempotency_key is not None: options["idempotency_key"] = idempotency_key if is_given(post_parser): # internal options["post_parser"] = post_parser # type: ignore if synthesize_event_and_data is not None: options["synthesize_event_and_data"] = synthesize_event_and_data return options class ForceMultipartDict(Dict[str, None]): def __bool__(self) -> bool: return True class OtherPlatform: def __init__(self, name: str) -> None: self.name = name @override def __str__(self) -> str: return f"Other:{self.name}" Platform = Union[ OtherPlatform, Literal[ "MacOS", "Linux", "Windows", "FreeBSD", "OpenBSD", "iOS", "Android", "Unknown", ], ] def get_platform() -> Platform: try: system = platform.system().lower() platform_name = platform.platform().lower() except Exception: return "Unknown" if "iphone" in platform_name or "ipad" in platform_name: # Tested using Python3IDE on an iPhone 11 and Pythonista on an iPad 7 # system is Darwin and platform_name is a string like: # - Darwin-21.6.0-iPhone12,1-64bit # - Darwin-21.6.0-iPad7,11-64bit return "iOS" if system == "darwin": return "MacOS" if system == "windows": return "Windows" if "android" in platform_name: # Tested using Pydroid 3 # system is Linux and platform_name is a string like 'Linux-5.10.81-android12-9-00001-geba40aecb3b7-ab8534902-aarch64-with-libc' return "Android" if system == "linux": # https://distro.readthedocs.io/en/latest/#distro.id distro_id = distro.id() if distro_id == "freebsd": return "FreeBSD" if distro_id == "openbsd": return "OpenBSD" return "Linux" if platform_name: return OtherPlatform(platform_name) return "Unknown" @lru_cache(maxsize=None) def platform_headers(version: str, *, platform: Platform | None) -> Dict[str, str]: return { "X-Stainless-Lang": "python", "X-Stainless-Package-Version": version, "X-Stainless-OS": str(platform or get_platform()), "X-Stainless-Arch": str(get_architecture()), "X-Stainless-Runtime": get_python_runtime(), "X-Stainless-Runtime-Version": get_python_version(), } class OtherArch: def __init__(self, name: str) -> None: self.name = name @override def __str__(self) -> str: return f"other:{self.name}" Arch = Union[OtherArch, Literal["x32", "x64", "arm", "arm64", "unknown"]] def get_python_runtime() -> str: try: return platform.python_implementation() except Exception: return "unknown" def get_python_version() -> str: try: return platform.python_version() except Exception: return "unknown" def get_architecture() -> Arch: try: machine = platform.machine().lower() except Exception: return "unknown" if machine in ("arm64", "aarch64"): return "arm64" # TODO: untested if machine == "arm": return "arm" if machine == "x86_64": return "x64" # TODO: untested if sys.maxsize <= 2**32: return "x32" if machine: return OtherArch(machine) return "unknown" def _merge_mappings( obj1: Mapping[_T_co, Union[_T, Omit]], obj2: Mapping[_T_co, Union[_T, Omit]], ) -> Dict[_T_co, _T]: """Merge two mappings of the same type, removing any values that are instances of `Omit`. In cases with duplicate keys the second mapping takes precedence. """ merged = {**obj1, **obj2} return {key: value for key, value in merged.items() if not isinstance(value, Omit)} ================================================ FILE: src/openai/_client.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import TYPE_CHECKING, Any, Mapping, Callable, Awaitable from typing_extensions import Self, override import httpx from . import _exceptions from ._qs import Querystring from ._types import ( Omit, Timeout, NotGiven, Transport, ProxiesTypes, RequestOptions, not_given, ) from ._utils import ( is_given, is_mapping, get_async_library, ) from ._compat import cached_property from ._models import FinalRequestOptions from ._version import __version__ from ._streaming import Stream as Stream, AsyncStream as AsyncStream from ._exceptions import OpenAIError, APIStatusError from ._base_client import ( DEFAULT_MAX_RETRIES, SyncAPIClient, AsyncAPIClient, ) if TYPE_CHECKING: from .resources import ( beta, chat, audio, evals, files, images, models, skills, videos, batches, uploads, realtime, responses, containers, embeddings, completions, fine_tuning, moderations, conversations, vector_stores, ) from .resources.files import Files, AsyncFiles from .resources.images import Images, AsyncImages from .resources.models import Models, AsyncModels from .resources.videos import Videos, AsyncVideos from .resources.batches import Batches, AsyncBatches from .resources.beta.beta import Beta, AsyncBeta from .resources.chat.chat import Chat, AsyncChat from .resources.embeddings import Embeddings, AsyncEmbeddings from .resources.audio.audio import Audio, AsyncAudio from .resources.completions import Completions, AsyncCompletions from .resources.evals.evals import Evals, AsyncEvals from .resources.moderations import Moderations, AsyncModerations from .resources.skills.skills import Skills, AsyncSkills from .resources.uploads.uploads import Uploads, AsyncUploads from .resources.realtime.realtime import Realtime, AsyncRealtime from .resources.webhooks.webhooks import Webhooks, AsyncWebhooks from .resources.responses.responses import Responses, AsyncResponses from .resources.containers.containers import Containers, AsyncContainers from .resources.fine_tuning.fine_tuning import FineTuning, AsyncFineTuning from .resources.conversations.conversations import Conversations, AsyncConversations from .resources.vector_stores.vector_stores import VectorStores, AsyncVectorStores __all__ = ["Timeout", "Transport", "ProxiesTypes", "RequestOptions", "OpenAI", "AsyncOpenAI", "Client", "AsyncClient"] class OpenAI(SyncAPIClient): # client options api_key: str organization: str | None project: str | None webhook_secret: str | None websocket_base_url: str | httpx.URL | None """Base URL for WebSocket connections. If not specified, the default base URL will be used, with 'wss://' replacing the 'http://' or 'https://' scheme. For example: 'http://example.com' becomes 'wss://example.com' """ def __init__( self, *, api_key: str | None | Callable[[], str] = None, organization: str | None = None, project: str | None = None, webhook_secret: str | None = None, base_url: str | httpx.URL | None = None, websocket_base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, # Configure a custom httpx client. # We provide a `DefaultHttpxClient` class that you can pass to retain the default values we use for `limits`, `timeout` & `follow_redirects`. # See the [httpx documentation](https://www.python-httpx.org/api/#client) for more details. http_client: httpx.Client | None = None, # Enable or disable schema validation for data returned by the API. # When enabled an error APIResponseValidationError is raised # if the API responds with invalid data for the expected schema. # # This parameter may be removed or changed in the future. # If you rely on this feature, please open a GitHub issue # outlining your use-case to help us decide if it should be # part of our public interface in the future. _strict_response_validation: bool = False, ) -> None: """Construct a new synchronous OpenAI client instance. This automatically infers the following arguments from their corresponding environment variables if they are not provided: - `api_key` from `OPENAI_API_KEY` - `organization` from `OPENAI_ORG_ID` - `project` from `OPENAI_PROJECT_ID` - `webhook_secret` from `OPENAI_WEBHOOK_SECRET` """ if api_key is None: api_key = os.environ.get("OPENAI_API_KEY") if api_key is None: raise OpenAIError( "The api_key client option must be set either by passing api_key to the client or by setting the OPENAI_API_KEY environment variable" ) if callable(api_key): self.api_key = "" self._api_key_provider: Callable[[], str] | None = api_key else: self.api_key = api_key self._api_key_provider = None if organization is None: organization = os.environ.get("OPENAI_ORG_ID") self.organization = organization if project is None: project = os.environ.get("OPENAI_PROJECT_ID") self.project = project if webhook_secret is None: webhook_secret = os.environ.get("OPENAI_WEBHOOK_SECRET") self.webhook_secret = webhook_secret self.websocket_base_url = websocket_base_url if base_url is None: base_url = os.environ.get("OPENAI_BASE_URL") if base_url is None: base_url = f"https://api.openai.com/v1" super().__init__( version=__version__, base_url=base_url, max_retries=max_retries, timeout=timeout, http_client=http_client, custom_headers=default_headers, custom_query=default_query, _strict_response_validation=_strict_response_validation, ) self._default_stream_cls = Stream @cached_property def completions(self) -> Completions: """ Given a prompt, the model will return one or more predicted completions, and can also return the probabilities of alternative tokens at each position. """ from .resources.completions import Completions return Completions(self) @cached_property def chat(self) -> Chat: from .resources.chat import Chat return Chat(self) @cached_property def embeddings(self) -> Embeddings: """ Get a vector representation of a given input that can be easily consumed by machine learning models and algorithms. """ from .resources.embeddings import Embeddings return Embeddings(self) @cached_property def files(self) -> Files: """ Files are used to upload documents that can be used with features like Assistants and Fine-tuning. """ from .resources.files import Files return Files(self) @cached_property def images(self) -> Images: """Given a prompt and/or an input image, the model will generate a new image.""" from .resources.images import Images return Images(self) @cached_property def audio(self) -> Audio: from .resources.audio import Audio return Audio(self) @cached_property def moderations(self) -> Moderations: """ Given text and/or image inputs, classifies if those inputs are potentially harmful. """ from .resources.moderations import Moderations return Moderations(self) @cached_property def models(self) -> Models: """List and describe the various models available in the API.""" from .resources.models import Models return Models(self) @cached_property def fine_tuning(self) -> FineTuning: from .resources.fine_tuning import FineTuning return FineTuning(self) @cached_property def vector_stores(self) -> VectorStores: from .resources.vector_stores import VectorStores return VectorStores(self) @cached_property def webhooks(self) -> Webhooks: from .resources.webhooks import Webhooks return Webhooks(self) @cached_property def beta(self) -> Beta: from .resources.beta import Beta return Beta(self) @cached_property def batches(self) -> Batches: """Create large batches of API requests to run asynchronously.""" from .resources.batches import Batches return Batches(self) @cached_property def uploads(self) -> Uploads: """Use Uploads to upload large files in multiple parts.""" from .resources.uploads import Uploads return Uploads(self) @cached_property def responses(self) -> Responses: from .resources.responses import Responses return Responses(self) @cached_property def realtime(self) -> Realtime: from .resources.realtime import Realtime return Realtime(self) @cached_property def conversations(self) -> Conversations: """Manage conversations and conversation items.""" from .resources.conversations import Conversations return Conversations(self) @cached_property def evals(self) -> Evals: """Manage and run evals in the OpenAI platform.""" from .resources.evals import Evals return Evals(self) @cached_property def containers(self) -> Containers: from .resources.containers import Containers return Containers(self) @cached_property def skills(self) -> Skills: from .resources.skills import Skills return Skills(self) @cached_property def videos(self) -> Videos: from .resources.videos import Videos return Videos(self) @cached_property def with_raw_response(self) -> OpenAIWithRawResponse: return OpenAIWithRawResponse(self) @cached_property def with_streaming_response(self) -> OpenAIWithStreamedResponse: return OpenAIWithStreamedResponse(self) @property @override def qs(self) -> Querystring: return Querystring(array_format="brackets") def _refresh_api_key(self) -> None: if self._api_key_provider: self.api_key = self._api_key_provider() @override def _prepare_options(self, options: FinalRequestOptions) -> FinalRequestOptions: self._refresh_api_key() return super()._prepare_options(options) @property @override def auth_headers(self) -> dict[str, str]: api_key = self.api_key if not api_key: # if the api key is an empty string, encoding the header will fail return {} return {"Authorization": f"Bearer {api_key}"} @property @override def default_headers(self) -> dict[str, str | Omit]: return { **super().default_headers, "X-Stainless-Async": "false", "OpenAI-Organization": self.organization if self.organization is not None else Omit(), "OpenAI-Project": self.project if self.project is not None else Omit(), **self._custom_headers, } def copy( self, *, api_key: str | Callable[[], str] | None = None, organization: str | None = None, project: str | None = None, webhook_secret: str | None = None, websocket_base_url: str | httpx.URL | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.Client | None = None, max_retries: int | NotGiven = not_given, default_headers: Mapping[str, str] | None = None, set_default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, set_default_query: Mapping[str, object] | None = None, _extra_kwargs: Mapping[str, Any] = {}, ) -> Self: """ Create a new client instance re-using the same options given to the current client with optional overriding. """ if default_headers is not None and set_default_headers is not None: raise ValueError("The `default_headers` and `set_default_headers` arguments are mutually exclusive") if default_query is not None and set_default_query is not None: raise ValueError("The `default_query` and `set_default_query` arguments are mutually exclusive") headers = self._custom_headers if default_headers is not None: headers = {**headers, **default_headers} elif set_default_headers is not None: headers = set_default_headers params = self._custom_query if default_query is not None: params = {**params, **default_query} elif set_default_query is not None: params = set_default_query http_client = http_client or self._client return self.__class__( api_key=api_key or self._api_key_provider or self.api_key, organization=organization or self.organization, project=project or self.project, webhook_secret=webhook_secret or self.webhook_secret, websocket_base_url=websocket_base_url or self.websocket_base_url, base_url=base_url or self.base_url, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, max_retries=max_retries if is_given(max_retries) else self.max_retries, default_headers=headers, default_query=params, **_extra_kwargs, ) # Alias for `copy` for nicer inline usage, e.g. # client.with_options(timeout=10).foo.create(...) with_options = copy @override def _make_status_error( self, err_msg: str, *, body: object, response: httpx.Response, ) -> APIStatusError: data = body.get("error", body) if is_mapping(body) else body if response.status_code == 400: return _exceptions.BadRequestError(err_msg, response=response, body=data) if response.status_code == 401: return _exceptions.AuthenticationError(err_msg, response=response, body=data) if response.status_code == 403: return _exceptions.PermissionDeniedError(err_msg, response=response, body=data) if response.status_code == 404: return _exceptions.NotFoundError(err_msg, response=response, body=data) if response.status_code == 409: return _exceptions.ConflictError(err_msg, response=response, body=data) if response.status_code == 422: return _exceptions.UnprocessableEntityError(err_msg, response=response, body=data) if response.status_code == 429: return _exceptions.RateLimitError(err_msg, response=response, body=data) if response.status_code >= 500: return _exceptions.InternalServerError(err_msg, response=response, body=data) return APIStatusError(err_msg, response=response, body=data) class AsyncOpenAI(AsyncAPIClient): # client options api_key: str organization: str | None project: str | None webhook_secret: str | None websocket_base_url: str | httpx.URL | None """Base URL for WebSocket connections. If not specified, the default base URL will be used, with 'wss://' replacing the 'http://' or 'https://' scheme. For example: 'http://example.com' becomes 'wss://example.com' """ def __init__( self, *, api_key: str | Callable[[], Awaitable[str]] | None = None, organization: str | None = None, project: str | None = None, webhook_secret: str | None = None, base_url: str | httpx.URL | None = None, websocket_base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, # Configure a custom httpx client. # We provide a `DefaultAsyncHttpxClient` class that you can pass to retain the default values we use for `limits`, `timeout` & `follow_redirects`. # See the [httpx documentation](https://www.python-httpx.org/api/#asyncclient) for more details. http_client: httpx.AsyncClient | None = None, # Enable or disable schema validation for data returned by the API. # When enabled an error APIResponseValidationError is raised # if the API responds with invalid data for the expected schema. # # This parameter may be removed or changed in the future. # If you rely on this feature, please open a GitHub issue # outlining your use-case to help us decide if it should be # part of our public interface in the future. _strict_response_validation: bool = False, ) -> None: """Construct a new async AsyncOpenAI client instance. This automatically infers the following arguments from their corresponding environment variables if they are not provided: - `api_key` from `OPENAI_API_KEY` - `organization` from `OPENAI_ORG_ID` - `project` from `OPENAI_PROJECT_ID` - `webhook_secret` from `OPENAI_WEBHOOK_SECRET` """ if api_key is None: api_key = os.environ.get("OPENAI_API_KEY") if api_key is None: raise OpenAIError( "The api_key client option must be set either by passing api_key to the client or by setting the OPENAI_API_KEY environment variable" ) if callable(api_key): self.api_key = "" self._api_key_provider: Callable[[], Awaitable[str]] | None = api_key else: self.api_key = api_key self._api_key_provider = None if organization is None: organization = os.environ.get("OPENAI_ORG_ID") self.organization = organization if project is None: project = os.environ.get("OPENAI_PROJECT_ID") self.project = project if webhook_secret is None: webhook_secret = os.environ.get("OPENAI_WEBHOOK_SECRET") self.webhook_secret = webhook_secret self.websocket_base_url = websocket_base_url if base_url is None: base_url = os.environ.get("OPENAI_BASE_URL") if base_url is None: base_url = f"https://api.openai.com/v1" super().__init__( version=__version__, base_url=base_url, max_retries=max_retries, timeout=timeout, http_client=http_client, custom_headers=default_headers, custom_query=default_query, _strict_response_validation=_strict_response_validation, ) self._default_stream_cls = AsyncStream @cached_property def completions(self) -> AsyncCompletions: """ Given a prompt, the model will return one or more predicted completions, and can also return the probabilities of alternative tokens at each position. """ from .resources.completions import AsyncCompletions return AsyncCompletions(self) @cached_property def chat(self) -> AsyncChat: from .resources.chat import AsyncChat return AsyncChat(self) @cached_property def embeddings(self) -> AsyncEmbeddings: """ Get a vector representation of a given input that can be easily consumed by machine learning models and algorithms. """ from .resources.embeddings import AsyncEmbeddings return AsyncEmbeddings(self) @cached_property def files(self) -> AsyncFiles: """ Files are used to upload documents that can be used with features like Assistants and Fine-tuning. """ from .resources.files import AsyncFiles return AsyncFiles(self) @cached_property def images(self) -> AsyncImages: """Given a prompt and/or an input image, the model will generate a new image.""" from .resources.images import AsyncImages return AsyncImages(self) @cached_property def audio(self) -> AsyncAudio: from .resources.audio import AsyncAudio return AsyncAudio(self) @cached_property def moderations(self) -> AsyncModerations: """ Given text and/or image inputs, classifies if those inputs are potentially harmful. """ from .resources.moderations import AsyncModerations return AsyncModerations(self) @cached_property def models(self) -> AsyncModels: """List and describe the various models available in the API.""" from .resources.models import AsyncModels return AsyncModels(self) @cached_property def fine_tuning(self) -> AsyncFineTuning: from .resources.fine_tuning import AsyncFineTuning return AsyncFineTuning(self) @cached_property def vector_stores(self) -> AsyncVectorStores: from .resources.vector_stores import AsyncVectorStores return AsyncVectorStores(self) @cached_property def webhooks(self) -> AsyncWebhooks: from .resources.webhooks import AsyncWebhooks return AsyncWebhooks(self) @cached_property def beta(self) -> AsyncBeta: from .resources.beta import AsyncBeta return AsyncBeta(self) @cached_property def batches(self) -> AsyncBatches: """Create large batches of API requests to run asynchronously.""" from .resources.batches import AsyncBatches return AsyncBatches(self) @cached_property def uploads(self) -> AsyncUploads: """Use Uploads to upload large files in multiple parts.""" from .resources.uploads import AsyncUploads return AsyncUploads(self) @cached_property def responses(self) -> AsyncResponses: from .resources.responses import AsyncResponses return AsyncResponses(self) @cached_property def realtime(self) -> AsyncRealtime: from .resources.realtime import AsyncRealtime return AsyncRealtime(self) @cached_property def conversations(self) -> AsyncConversations: """Manage conversations and conversation items.""" from .resources.conversations import AsyncConversations return AsyncConversations(self) @cached_property def evals(self) -> AsyncEvals: """Manage and run evals in the OpenAI platform.""" from .resources.evals import AsyncEvals return AsyncEvals(self) @cached_property def containers(self) -> AsyncContainers: from .resources.containers import AsyncContainers return AsyncContainers(self) @cached_property def skills(self) -> AsyncSkills: from .resources.skills import AsyncSkills return AsyncSkills(self) @cached_property def videos(self) -> AsyncVideos: from .resources.videos import AsyncVideos return AsyncVideos(self) @cached_property def with_raw_response(self) -> AsyncOpenAIWithRawResponse: return AsyncOpenAIWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncOpenAIWithStreamedResponse: return AsyncOpenAIWithStreamedResponse(self) @property @override def qs(self) -> Querystring: return Querystring(array_format="brackets") async def _refresh_api_key(self) -> None: if self._api_key_provider: self.api_key = await self._api_key_provider() @override async def _prepare_options(self, options: FinalRequestOptions) -> FinalRequestOptions: await self._refresh_api_key() return await super()._prepare_options(options) @property @override def auth_headers(self) -> dict[str, str]: api_key = self.api_key if not api_key: # if the api key is an empty string, encoding the header will fail return {} return {"Authorization": f"Bearer {api_key}"} @property @override def default_headers(self) -> dict[str, str | Omit]: return { **super().default_headers, "X-Stainless-Async": f"async:{get_async_library()}", "OpenAI-Organization": self.organization if self.organization is not None else Omit(), "OpenAI-Project": self.project if self.project is not None else Omit(), **self._custom_headers, } def copy( self, *, api_key: str | Callable[[], Awaitable[str]] | None = None, organization: str | None = None, project: str | None = None, webhook_secret: str | None = None, websocket_base_url: str | httpx.URL | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.AsyncClient | None = None, max_retries: int | NotGiven = not_given, default_headers: Mapping[str, str] | None = None, set_default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, set_default_query: Mapping[str, object] | None = None, _extra_kwargs: Mapping[str, Any] = {}, ) -> Self: """ Create a new client instance re-using the same options given to the current client with optional overriding. """ if default_headers is not None and set_default_headers is not None: raise ValueError("The `default_headers` and `set_default_headers` arguments are mutually exclusive") if default_query is not None and set_default_query is not None: raise ValueError("The `default_query` and `set_default_query` arguments are mutually exclusive") headers = self._custom_headers if default_headers is not None: headers = {**headers, **default_headers} elif set_default_headers is not None: headers = set_default_headers params = self._custom_query if default_query is not None: params = {**params, **default_query} elif set_default_query is not None: params = set_default_query http_client = http_client or self._client return self.__class__( api_key=api_key or self._api_key_provider or self.api_key, organization=organization or self.organization, project=project or self.project, webhook_secret=webhook_secret or self.webhook_secret, websocket_base_url=websocket_base_url or self.websocket_base_url, base_url=base_url or self.base_url, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, max_retries=max_retries if is_given(max_retries) else self.max_retries, default_headers=headers, default_query=params, **_extra_kwargs, ) # Alias for `copy` for nicer inline usage, e.g. # client.with_options(timeout=10).foo.create(...) with_options = copy @override def _make_status_error( self, err_msg: str, *, body: object, response: httpx.Response, ) -> APIStatusError: data = body.get("error", body) if is_mapping(body) else body if response.status_code == 400: return _exceptions.BadRequestError(err_msg, response=response, body=data) if response.status_code == 401: return _exceptions.AuthenticationError(err_msg, response=response, body=data) if response.status_code == 403: return _exceptions.PermissionDeniedError(err_msg, response=response, body=data) if response.status_code == 404: return _exceptions.NotFoundError(err_msg, response=response, body=data) if response.status_code == 409: return _exceptions.ConflictError(err_msg, response=response, body=data) if response.status_code == 422: return _exceptions.UnprocessableEntityError(err_msg, response=response, body=data) if response.status_code == 429: return _exceptions.RateLimitError(err_msg, response=response, body=data) if response.status_code >= 500: return _exceptions.InternalServerError(err_msg, response=response, body=data) return APIStatusError(err_msg, response=response, body=data) class OpenAIWithRawResponse: _client: OpenAI def __init__(self, client: OpenAI) -> None: self._client = client @cached_property def completions(self) -> completions.CompletionsWithRawResponse: """ Given a prompt, the model will return one or more predicted completions, and can also return the probabilities of alternative tokens at each position. """ from .resources.completions import CompletionsWithRawResponse return CompletionsWithRawResponse(self._client.completions) @cached_property def chat(self) -> chat.ChatWithRawResponse: from .resources.chat import ChatWithRawResponse return ChatWithRawResponse(self._client.chat) @cached_property def embeddings(self) -> embeddings.EmbeddingsWithRawResponse: """ Get a vector representation of a given input that can be easily consumed by machine learning models and algorithms. """ from .resources.embeddings import EmbeddingsWithRawResponse return EmbeddingsWithRawResponse(self._client.embeddings) @cached_property def files(self) -> files.FilesWithRawResponse: """ Files are used to upload documents that can be used with features like Assistants and Fine-tuning. """ from .resources.files import FilesWithRawResponse return FilesWithRawResponse(self._client.files) @cached_property def images(self) -> images.ImagesWithRawResponse: """Given a prompt and/or an input image, the model will generate a new image.""" from .resources.images import ImagesWithRawResponse return ImagesWithRawResponse(self._client.images) @cached_property def audio(self) -> audio.AudioWithRawResponse: from .resources.audio import AudioWithRawResponse return AudioWithRawResponse(self._client.audio) @cached_property def moderations(self) -> moderations.ModerationsWithRawResponse: """ Given text and/or image inputs, classifies if those inputs are potentially harmful. """ from .resources.moderations import ModerationsWithRawResponse return ModerationsWithRawResponse(self._client.moderations) @cached_property def models(self) -> models.ModelsWithRawResponse: """List and describe the various models available in the API.""" from .resources.models import ModelsWithRawResponse return ModelsWithRawResponse(self._client.models) @cached_property def fine_tuning(self) -> fine_tuning.FineTuningWithRawResponse: from .resources.fine_tuning import FineTuningWithRawResponse return FineTuningWithRawResponse(self._client.fine_tuning) @cached_property def vector_stores(self) -> vector_stores.VectorStoresWithRawResponse: from .resources.vector_stores import VectorStoresWithRawResponse return VectorStoresWithRawResponse(self._client.vector_stores) @cached_property def beta(self) -> beta.BetaWithRawResponse: from .resources.beta import BetaWithRawResponse return BetaWithRawResponse(self._client.beta) @cached_property def batches(self) -> batches.BatchesWithRawResponse: """Create large batches of API requests to run asynchronously.""" from .resources.batches import BatchesWithRawResponse return BatchesWithRawResponse(self._client.batches) @cached_property def uploads(self) -> uploads.UploadsWithRawResponse: """Use Uploads to upload large files in multiple parts.""" from .resources.uploads import UploadsWithRawResponse return UploadsWithRawResponse(self._client.uploads) @cached_property def responses(self) -> responses.ResponsesWithRawResponse: from .resources.responses import ResponsesWithRawResponse return ResponsesWithRawResponse(self._client.responses) @cached_property def realtime(self) -> realtime.RealtimeWithRawResponse: from .resources.realtime import RealtimeWithRawResponse return RealtimeWithRawResponse(self._client.realtime) @cached_property def conversations(self) -> conversations.ConversationsWithRawResponse: """Manage conversations and conversation items.""" from .resources.conversations import ConversationsWithRawResponse return ConversationsWithRawResponse(self._client.conversations) @cached_property def evals(self) -> evals.EvalsWithRawResponse: """Manage and run evals in the OpenAI platform.""" from .resources.evals import EvalsWithRawResponse return EvalsWithRawResponse(self._client.evals) @cached_property def containers(self) -> containers.ContainersWithRawResponse: from .resources.containers import ContainersWithRawResponse return ContainersWithRawResponse(self._client.containers) @cached_property def skills(self) -> skills.SkillsWithRawResponse: from .resources.skills import SkillsWithRawResponse return SkillsWithRawResponse(self._client.skills) @cached_property def videos(self) -> videos.VideosWithRawResponse: from .resources.videos import VideosWithRawResponse return VideosWithRawResponse(self._client.videos) class AsyncOpenAIWithRawResponse: _client: AsyncOpenAI def __init__(self, client: AsyncOpenAI) -> None: self._client = client @cached_property def completions(self) -> completions.AsyncCompletionsWithRawResponse: """ Given a prompt, the model will return one or more predicted completions, and can also return the probabilities of alternative tokens at each position. """ from .resources.completions import AsyncCompletionsWithRawResponse return AsyncCompletionsWithRawResponse(self._client.completions) @cached_property def chat(self) -> chat.AsyncChatWithRawResponse: from .resources.chat import AsyncChatWithRawResponse return AsyncChatWithRawResponse(self._client.chat) @cached_property def embeddings(self) -> embeddings.AsyncEmbeddingsWithRawResponse: """ Get a vector representation of a given input that can be easily consumed by machine learning models and algorithms. """ from .resources.embeddings import AsyncEmbeddingsWithRawResponse return AsyncEmbeddingsWithRawResponse(self._client.embeddings) @cached_property def files(self) -> files.AsyncFilesWithRawResponse: """ Files are used to upload documents that can be used with features like Assistants and Fine-tuning. """ from .resources.files import AsyncFilesWithRawResponse return AsyncFilesWithRawResponse(self._client.files) @cached_property def images(self) -> images.AsyncImagesWithRawResponse: """Given a prompt and/or an input image, the model will generate a new image.""" from .resources.images import AsyncImagesWithRawResponse return AsyncImagesWithRawResponse(self._client.images) @cached_property def audio(self) -> audio.AsyncAudioWithRawResponse: from .resources.audio import AsyncAudioWithRawResponse return AsyncAudioWithRawResponse(self._client.audio) @cached_property def moderations(self) -> moderations.AsyncModerationsWithRawResponse: """ Given text and/or image inputs, classifies if those inputs are potentially harmful. """ from .resources.moderations import AsyncModerationsWithRawResponse return AsyncModerationsWithRawResponse(self._client.moderations) @cached_property def models(self) -> models.AsyncModelsWithRawResponse: """List and describe the various models available in the API.""" from .resources.models import AsyncModelsWithRawResponse return AsyncModelsWithRawResponse(self._client.models) @cached_property def fine_tuning(self) -> fine_tuning.AsyncFineTuningWithRawResponse: from .resources.fine_tuning import AsyncFineTuningWithRawResponse return AsyncFineTuningWithRawResponse(self._client.fine_tuning) @cached_property def vector_stores(self) -> vector_stores.AsyncVectorStoresWithRawResponse: from .resources.vector_stores import AsyncVectorStoresWithRawResponse return AsyncVectorStoresWithRawResponse(self._client.vector_stores) @cached_property def beta(self) -> beta.AsyncBetaWithRawResponse: from .resources.beta import AsyncBetaWithRawResponse return AsyncBetaWithRawResponse(self._client.beta) @cached_property def batches(self) -> batches.AsyncBatchesWithRawResponse: """Create large batches of API requests to run asynchronously.""" from .resources.batches import AsyncBatchesWithRawResponse return AsyncBatchesWithRawResponse(self._client.batches) @cached_property def uploads(self) -> uploads.AsyncUploadsWithRawResponse: """Use Uploads to upload large files in multiple parts.""" from .resources.uploads import AsyncUploadsWithRawResponse return AsyncUploadsWithRawResponse(self._client.uploads) @cached_property def responses(self) -> responses.AsyncResponsesWithRawResponse: from .resources.responses import AsyncResponsesWithRawResponse return AsyncResponsesWithRawResponse(self._client.responses) @cached_property def realtime(self) -> realtime.AsyncRealtimeWithRawResponse: from .resources.realtime import AsyncRealtimeWithRawResponse return AsyncRealtimeWithRawResponse(self._client.realtime) @cached_property def conversations(self) -> conversations.AsyncConversationsWithRawResponse: """Manage conversations and conversation items.""" from .resources.conversations import AsyncConversationsWithRawResponse return AsyncConversationsWithRawResponse(self._client.conversations) @cached_property def evals(self) -> evals.AsyncEvalsWithRawResponse: """Manage and run evals in the OpenAI platform.""" from .resources.evals import AsyncEvalsWithRawResponse return AsyncEvalsWithRawResponse(self._client.evals) @cached_property def containers(self) -> containers.AsyncContainersWithRawResponse: from .resources.containers import AsyncContainersWithRawResponse return AsyncContainersWithRawResponse(self._client.containers) @cached_property def skills(self) -> skills.AsyncSkillsWithRawResponse: from .resources.skills import AsyncSkillsWithRawResponse return AsyncSkillsWithRawResponse(self._client.skills) @cached_property def videos(self) -> videos.AsyncVideosWithRawResponse: from .resources.videos import AsyncVideosWithRawResponse return AsyncVideosWithRawResponse(self._client.videos) class OpenAIWithStreamedResponse: _client: OpenAI def __init__(self, client: OpenAI) -> None: self._client = client @cached_property def completions(self) -> completions.CompletionsWithStreamingResponse: """ Given a prompt, the model will return one or more predicted completions, and can also return the probabilities of alternative tokens at each position. """ from .resources.completions import CompletionsWithStreamingResponse return CompletionsWithStreamingResponse(self._client.completions) @cached_property def chat(self) -> chat.ChatWithStreamingResponse: from .resources.chat import ChatWithStreamingResponse return ChatWithStreamingResponse(self._client.chat) @cached_property def embeddings(self) -> embeddings.EmbeddingsWithStreamingResponse: """ Get a vector representation of a given input that can be easily consumed by machine learning models and algorithms. """ from .resources.embeddings import EmbeddingsWithStreamingResponse return EmbeddingsWithStreamingResponse(self._client.embeddings) @cached_property def files(self) -> files.FilesWithStreamingResponse: """ Files are used to upload documents that can be used with features like Assistants and Fine-tuning. """ from .resources.files import FilesWithStreamingResponse return FilesWithStreamingResponse(self._client.files) @cached_property def images(self) -> images.ImagesWithStreamingResponse: """Given a prompt and/or an input image, the model will generate a new image.""" from .resources.images import ImagesWithStreamingResponse return ImagesWithStreamingResponse(self._client.images) @cached_property def audio(self) -> audio.AudioWithStreamingResponse: from .resources.audio import AudioWithStreamingResponse return AudioWithStreamingResponse(self._client.audio) @cached_property def moderations(self) -> moderations.ModerationsWithStreamingResponse: """ Given text and/or image inputs, classifies if those inputs are potentially harmful. """ from .resources.moderations import ModerationsWithStreamingResponse return ModerationsWithStreamingResponse(self._client.moderations) @cached_property def models(self) -> models.ModelsWithStreamingResponse: """List and describe the various models available in the API.""" from .resources.models import ModelsWithStreamingResponse return ModelsWithStreamingResponse(self._client.models) @cached_property def fine_tuning(self) -> fine_tuning.FineTuningWithStreamingResponse: from .resources.fine_tuning import FineTuningWithStreamingResponse return FineTuningWithStreamingResponse(self._client.fine_tuning) @cached_property def vector_stores(self) -> vector_stores.VectorStoresWithStreamingResponse: from .resources.vector_stores import VectorStoresWithStreamingResponse return VectorStoresWithStreamingResponse(self._client.vector_stores) @cached_property def beta(self) -> beta.BetaWithStreamingResponse: from .resources.beta import BetaWithStreamingResponse return BetaWithStreamingResponse(self._client.beta) @cached_property def batches(self) -> batches.BatchesWithStreamingResponse: """Create large batches of API requests to run asynchronously.""" from .resources.batches import BatchesWithStreamingResponse return BatchesWithStreamingResponse(self._client.batches) @cached_property def uploads(self) -> uploads.UploadsWithStreamingResponse: """Use Uploads to upload large files in multiple parts.""" from .resources.uploads import UploadsWithStreamingResponse return UploadsWithStreamingResponse(self._client.uploads) @cached_property def responses(self) -> responses.ResponsesWithStreamingResponse: from .resources.responses import ResponsesWithStreamingResponse return ResponsesWithStreamingResponse(self._client.responses) @cached_property def realtime(self) -> realtime.RealtimeWithStreamingResponse: from .resources.realtime import RealtimeWithStreamingResponse return RealtimeWithStreamingResponse(self._client.realtime) @cached_property def conversations(self) -> conversations.ConversationsWithStreamingResponse: """Manage conversations and conversation items.""" from .resources.conversations import ConversationsWithStreamingResponse return ConversationsWithStreamingResponse(self._client.conversations) @cached_property def evals(self) -> evals.EvalsWithStreamingResponse: """Manage and run evals in the OpenAI platform.""" from .resources.evals import EvalsWithStreamingResponse return EvalsWithStreamingResponse(self._client.evals) @cached_property def containers(self) -> containers.ContainersWithStreamingResponse: from .resources.containers import ContainersWithStreamingResponse return ContainersWithStreamingResponse(self._client.containers) @cached_property def skills(self) -> skills.SkillsWithStreamingResponse: from .resources.skills import SkillsWithStreamingResponse return SkillsWithStreamingResponse(self._client.skills) @cached_property def videos(self) -> videos.VideosWithStreamingResponse: from .resources.videos import VideosWithStreamingResponse return VideosWithStreamingResponse(self._client.videos) class AsyncOpenAIWithStreamedResponse: _client: AsyncOpenAI def __init__(self, client: AsyncOpenAI) -> None: self._client = client @cached_property def completions(self) -> completions.AsyncCompletionsWithStreamingResponse: """ Given a prompt, the model will return one or more predicted completions, and can also return the probabilities of alternative tokens at each position. """ from .resources.completions import AsyncCompletionsWithStreamingResponse return AsyncCompletionsWithStreamingResponse(self._client.completions) @cached_property def chat(self) -> chat.AsyncChatWithStreamingResponse: from .resources.chat import AsyncChatWithStreamingResponse return AsyncChatWithStreamingResponse(self._client.chat) @cached_property def embeddings(self) -> embeddings.AsyncEmbeddingsWithStreamingResponse: """ Get a vector representation of a given input that can be easily consumed by machine learning models and algorithms. """ from .resources.embeddings import AsyncEmbeddingsWithStreamingResponse return AsyncEmbeddingsWithStreamingResponse(self._client.embeddings) @cached_property def files(self) -> files.AsyncFilesWithStreamingResponse: """ Files are used to upload documents that can be used with features like Assistants and Fine-tuning. """ from .resources.files import AsyncFilesWithStreamingResponse return AsyncFilesWithStreamingResponse(self._client.files) @cached_property def images(self) -> images.AsyncImagesWithStreamingResponse: """Given a prompt and/or an input image, the model will generate a new image.""" from .resources.images import AsyncImagesWithStreamingResponse return AsyncImagesWithStreamingResponse(self._client.images) @cached_property def audio(self) -> audio.AsyncAudioWithStreamingResponse: from .resources.audio import AsyncAudioWithStreamingResponse return AsyncAudioWithStreamingResponse(self._client.audio) @cached_property def moderations(self) -> moderations.AsyncModerationsWithStreamingResponse: """ Given text and/or image inputs, classifies if those inputs are potentially harmful. """ from .resources.moderations import AsyncModerationsWithStreamingResponse return AsyncModerationsWithStreamingResponse(self._client.moderations) @cached_property def models(self) -> models.AsyncModelsWithStreamingResponse: """List and describe the various models available in the API.""" from .resources.models import AsyncModelsWithStreamingResponse return AsyncModelsWithStreamingResponse(self._client.models) @cached_property def fine_tuning(self) -> fine_tuning.AsyncFineTuningWithStreamingResponse: from .resources.fine_tuning import AsyncFineTuningWithStreamingResponse return AsyncFineTuningWithStreamingResponse(self._client.fine_tuning) @cached_property def vector_stores(self) -> vector_stores.AsyncVectorStoresWithStreamingResponse: from .resources.vector_stores import AsyncVectorStoresWithStreamingResponse return AsyncVectorStoresWithStreamingResponse(self._client.vector_stores) @cached_property def beta(self) -> beta.AsyncBetaWithStreamingResponse: from .resources.beta import AsyncBetaWithStreamingResponse return AsyncBetaWithStreamingResponse(self._client.beta) @cached_property def batches(self) -> batches.AsyncBatchesWithStreamingResponse: """Create large batches of API requests to run asynchronously.""" from .resources.batches import AsyncBatchesWithStreamingResponse return AsyncBatchesWithStreamingResponse(self._client.batches) @cached_property def uploads(self) -> uploads.AsyncUploadsWithStreamingResponse: """Use Uploads to upload large files in multiple parts.""" from .resources.uploads import AsyncUploadsWithStreamingResponse return AsyncUploadsWithStreamingResponse(self._client.uploads) @cached_property def responses(self) -> responses.AsyncResponsesWithStreamingResponse: from .resources.responses import AsyncResponsesWithStreamingResponse return AsyncResponsesWithStreamingResponse(self._client.responses) @cached_property def realtime(self) -> realtime.AsyncRealtimeWithStreamingResponse: from .resources.realtime import AsyncRealtimeWithStreamingResponse return AsyncRealtimeWithStreamingResponse(self._client.realtime) @cached_property def conversations(self) -> conversations.AsyncConversationsWithStreamingResponse: """Manage conversations and conversation items.""" from .resources.conversations import AsyncConversationsWithStreamingResponse return AsyncConversationsWithStreamingResponse(self._client.conversations) @cached_property def evals(self) -> evals.AsyncEvalsWithStreamingResponse: """Manage and run evals in the OpenAI platform.""" from .resources.evals import AsyncEvalsWithStreamingResponse return AsyncEvalsWithStreamingResponse(self._client.evals) @cached_property def containers(self) -> containers.AsyncContainersWithStreamingResponse: from .resources.containers import AsyncContainersWithStreamingResponse return AsyncContainersWithStreamingResponse(self._client.containers) @cached_property def skills(self) -> skills.AsyncSkillsWithStreamingResponse: from .resources.skills import AsyncSkillsWithStreamingResponse return AsyncSkillsWithStreamingResponse(self._client.skills) @cached_property def videos(self) -> videos.AsyncVideosWithStreamingResponse: from .resources.videos import AsyncVideosWithStreamingResponse return AsyncVideosWithStreamingResponse(self._client.videos) Client = OpenAI AsyncClient = AsyncOpenAI ================================================ FILE: src/openai/_compat.py ================================================ from __future__ import annotations from typing import TYPE_CHECKING, Any, Union, Generic, TypeVar, Callable, cast, overload from datetime import date, datetime from typing_extensions import Self, Literal, TypedDict import pydantic from pydantic.fields import FieldInfo from ._types import IncEx, StrBytesIntFloat _T = TypeVar("_T") _ModelT = TypeVar("_ModelT", bound=pydantic.BaseModel) # --------------- Pydantic v2, v3 compatibility --------------- # Pyright incorrectly reports some of our functions as overriding a method when they don't # pyright: reportIncompatibleMethodOverride=false PYDANTIC_V1 = pydantic.VERSION.startswith("1.") if TYPE_CHECKING: def parse_date(value: date | StrBytesIntFloat) -> date: # noqa: ARG001 ... def parse_datetime(value: Union[datetime, StrBytesIntFloat]) -> datetime: # noqa: ARG001 ... def get_args(t: type[Any]) -> tuple[Any, ...]: # noqa: ARG001 ... def is_union(tp: type[Any] | None) -> bool: # noqa: ARG001 ... def get_origin(t: type[Any]) -> type[Any] | None: # noqa: ARG001 ... def is_literal_type(type_: type[Any]) -> bool: # noqa: ARG001 ... def is_typeddict(type_: type[Any]) -> bool: # noqa: ARG001 ... else: # v1 re-exports if PYDANTIC_V1: from pydantic.typing import ( get_args as get_args, is_union as is_union, get_origin as get_origin, is_typeddict as is_typeddict, is_literal_type as is_literal_type, ) from pydantic.datetime_parse import parse_date as parse_date, parse_datetime as parse_datetime else: from ._utils import ( get_args as get_args, is_union as is_union, get_origin as get_origin, parse_date as parse_date, is_typeddict as is_typeddict, parse_datetime as parse_datetime, is_literal_type as is_literal_type, ) # refactored config if TYPE_CHECKING: from pydantic import ConfigDict as ConfigDict else: if PYDANTIC_V1: # TODO: provide an error message here? ConfigDict = None else: from pydantic import ConfigDict as ConfigDict # renamed methods / properties def parse_obj(model: type[_ModelT], value: object) -> _ModelT: if PYDANTIC_V1: return cast(_ModelT, model.parse_obj(value)) # pyright: ignore[reportDeprecated, reportUnnecessaryCast] else: return model.model_validate(value) def field_is_required(field: FieldInfo) -> bool: if PYDANTIC_V1: return field.required # type: ignore return field.is_required() def field_get_default(field: FieldInfo) -> Any: value = field.get_default() if PYDANTIC_V1: return value from pydantic_core import PydanticUndefined if value == PydanticUndefined: return None return value def field_outer_type(field: FieldInfo) -> Any: if PYDANTIC_V1: return field.outer_type_ # type: ignore return field.annotation def get_model_config(model: type[pydantic.BaseModel]) -> Any: if PYDANTIC_V1: return model.__config__ # type: ignore return model.model_config def get_model_fields(model: type[pydantic.BaseModel]) -> dict[str, FieldInfo]: if PYDANTIC_V1: return model.__fields__ # type: ignore return model.model_fields def model_copy(model: _ModelT, *, deep: bool = False) -> _ModelT: if PYDANTIC_V1: return model.copy(deep=deep) # type: ignore return model.model_copy(deep=deep) def model_json(model: pydantic.BaseModel, *, indent: int | None = None) -> str: if PYDANTIC_V1: return model.json(indent=indent) # type: ignore return model.model_dump_json(indent=indent) class _ModelDumpKwargs(TypedDict, total=False): by_alias: bool def model_dump( model: pydantic.BaseModel, *, exclude: IncEx | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, warnings: bool = True, mode: Literal["json", "python"] = "python", by_alias: bool | None = None, ) -> dict[str, Any]: if (not PYDANTIC_V1) or hasattr(model, "model_dump"): kwargs: _ModelDumpKwargs = {} if by_alias is not None: kwargs["by_alias"] = by_alias return model.model_dump( mode=mode, exclude=exclude, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, # warnings are not supported in Pydantic v1 warnings=True if PYDANTIC_V1 else warnings, **kwargs, ) return cast( "dict[str, Any]", model.dict( # pyright: ignore[reportDeprecated, reportUnnecessaryCast] exclude=exclude, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, by_alias=bool(by_alias) ), ) def model_parse(model: type[_ModelT], data: Any) -> _ModelT: if PYDANTIC_V1: return model.parse_obj(data) # pyright: ignore[reportDeprecated] return model.model_validate(data) def model_parse_json(model: type[_ModelT], data: str | bytes) -> _ModelT: if PYDANTIC_V1: return model.parse_raw(data) # pyright: ignore[reportDeprecated] return model.model_validate_json(data) def model_json_schema(model: type[_ModelT]) -> dict[str, Any]: if PYDANTIC_V1: return model.schema() # pyright: ignore[reportDeprecated] return model.model_json_schema() # generic models if TYPE_CHECKING: class GenericModel(pydantic.BaseModel): ... else: if PYDANTIC_V1: import pydantic.generics class GenericModel(pydantic.generics.GenericModel, pydantic.BaseModel): ... else: # there no longer needs to be a distinction in v2 but # we still have to create our own subclass to avoid # inconsistent MRO ordering errors class GenericModel(pydantic.BaseModel): ... # cached properties if TYPE_CHECKING: cached_property = property # we define a separate type (copied from typeshed) # that represents that `cached_property` is `set`able # at runtime, which differs from `@property`. # # this is a separate type as editors likely special case # `@property` and we don't want to cause issues just to have # more helpful internal types. class typed_cached_property(Generic[_T]): func: Callable[[Any], _T] attrname: str | None def __init__(self, func: Callable[[Any], _T]) -> None: ... @overload def __get__(self, instance: None, owner: type[Any] | None = None) -> Self: ... @overload def __get__(self, instance: object, owner: type[Any] | None = None) -> _T: ... def __get__(self, instance: object, owner: type[Any] | None = None) -> _T | Self: raise NotImplementedError() def __set_name__(self, owner: type[Any], name: str) -> None: ... # __set__ is not defined at runtime, but @cached_property is designed to be settable def __set__(self, instance: object, value: _T) -> None: ... else: from functools import cached_property as cached_property typed_cached_property = cached_property ================================================ FILE: src/openai/_constants.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import httpx RAW_RESPONSE_HEADER = "X-Stainless-Raw-Response" OVERRIDE_CAST_TO_HEADER = "____stainless_override_cast_to" # default timeout is 10 minutes DEFAULT_TIMEOUT = httpx.Timeout(timeout=600, connect=5.0) DEFAULT_MAX_RETRIES = 2 DEFAULT_CONNECTION_LIMITS = httpx.Limits(max_connections=1000, max_keepalive_connections=100) INITIAL_RETRY_DELAY = 0.5 MAX_RETRY_DELAY = 8.0 ================================================ FILE: src/openai/_exceptions.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import TYPE_CHECKING, Any, Optional, cast from typing_extensions import Literal import httpx from ._utils import is_dict from ._models import construct_type if TYPE_CHECKING: from .types.chat import ChatCompletion __all__ = [ "BadRequestError", "AuthenticationError", "PermissionDeniedError", "NotFoundError", "ConflictError", "UnprocessableEntityError", "RateLimitError", "InternalServerError", "LengthFinishReasonError", "ContentFilterFinishReasonError", "InvalidWebhookSignatureError", ] class OpenAIError(Exception): pass class APIError(OpenAIError): message: str request: httpx.Request body: object | None """The API response body. If the API responded with a valid JSON structure then this property will be the decoded result. If it isn't a valid JSON structure then this will be the raw response. If there was no response associated with this error then it will be `None`. """ code: Optional[str] = None param: Optional[str] = None type: Optional[str] def __init__(self, message: str, request: httpx.Request, *, body: object | None) -> None: super().__init__(message) self.request = request self.message = message self.body = body if is_dict(body): self.code = cast(Any, construct_type(type_=Optional[str], value=body.get("code"))) self.param = cast(Any, construct_type(type_=Optional[str], value=body.get("param"))) self.type = cast(Any, construct_type(type_=str, value=body.get("type"))) else: self.code = None self.param = None self.type = None class APIResponseValidationError(APIError): response: httpx.Response status_code: int def __init__(self, response: httpx.Response, body: object | None, *, message: str | None = None) -> None: super().__init__(message or "Data returned by API invalid for expected schema.", response.request, body=body) self.response = response self.status_code = response.status_code class APIStatusError(APIError): """Raised when an API response has a status code of 4xx or 5xx.""" response: httpx.Response status_code: int request_id: str | None def __init__(self, message: str, *, response: httpx.Response, body: object | None) -> None: super().__init__(message, response.request, body=body) self.response = response self.status_code = response.status_code self.request_id = response.headers.get("x-request-id") class APIConnectionError(APIError): def __init__(self, *, message: str = "Connection error.", request: httpx.Request) -> None: super().__init__(message, request, body=None) class APITimeoutError(APIConnectionError): def __init__(self, request: httpx.Request) -> None: super().__init__(message="Request timed out.", request=request) class BadRequestError(APIStatusError): status_code: Literal[400] = 400 # pyright: ignore[reportIncompatibleVariableOverride] class AuthenticationError(APIStatusError): status_code: Literal[401] = 401 # pyright: ignore[reportIncompatibleVariableOverride] class PermissionDeniedError(APIStatusError): status_code: Literal[403] = 403 # pyright: ignore[reportIncompatibleVariableOverride] class NotFoundError(APIStatusError): status_code: Literal[404] = 404 # pyright: ignore[reportIncompatibleVariableOverride] class ConflictError(APIStatusError): status_code: Literal[409] = 409 # pyright: ignore[reportIncompatibleVariableOverride] class UnprocessableEntityError(APIStatusError): status_code: Literal[422] = 422 # pyright: ignore[reportIncompatibleVariableOverride] class RateLimitError(APIStatusError): status_code: Literal[429] = 429 # pyright: ignore[reportIncompatibleVariableOverride] class InternalServerError(APIStatusError): pass class LengthFinishReasonError(OpenAIError): completion: ChatCompletion """The completion that caused this error. Note: this will *not* be a complete `ChatCompletion` object when streaming as `usage` will not be included. """ def __init__(self, *, completion: ChatCompletion) -> None: msg = "Could not parse response content as the length limit was reached" if completion.usage: msg += f" - {completion.usage}" super().__init__(msg) self.completion = completion class ContentFilterFinishReasonError(OpenAIError): def __init__(self) -> None: super().__init__( f"Could not parse response content as the request was rejected by the content filter", ) class InvalidWebhookSignatureError(ValueError): """Raised when a webhook signature is invalid, meaning the computed signature does not match the expected signature.""" ================================================ FILE: src/openai/_extras/__init__.py ================================================ from .numpy_proxy import numpy as numpy, has_numpy as has_numpy from .pandas_proxy import pandas as pandas from .sounddevice_proxy import sounddevice as sounddevice ================================================ FILE: src/openai/_extras/_common.py ================================================ from .._exceptions import OpenAIError INSTRUCTIONS = """ OpenAI error: missing `{library}` This feature requires additional dependencies: $ pip install openai[{extra}] """ def format_instructions(*, library: str, extra: str) -> str: return INSTRUCTIONS.format(library=library, extra=extra) class MissingDependencyError(OpenAIError): pass ================================================ FILE: src/openai/_extras/numpy_proxy.py ================================================ from __future__ import annotations from typing import TYPE_CHECKING, Any from typing_extensions import override from .._utils import LazyProxy from ._common import MissingDependencyError, format_instructions if TYPE_CHECKING: import numpy as numpy NUMPY_INSTRUCTIONS = format_instructions(library="numpy", extra="voice_helpers") class NumpyProxy(LazyProxy[Any]): @override def __load__(self) -> Any: try: import numpy except ImportError as err: raise MissingDependencyError(NUMPY_INSTRUCTIONS) from err return numpy if not TYPE_CHECKING: numpy = NumpyProxy() def has_numpy() -> bool: try: import numpy # noqa: F401 # pyright: ignore[reportUnusedImport] except ImportError: return False return True ================================================ FILE: src/openai/_extras/pandas_proxy.py ================================================ from __future__ import annotations from typing import TYPE_CHECKING, Any from typing_extensions import override from .._utils import LazyProxy from ._common import MissingDependencyError, format_instructions if TYPE_CHECKING: import pandas as pandas PANDAS_INSTRUCTIONS = format_instructions(library="pandas", extra="datalib") class PandasProxy(LazyProxy[Any]): @override def __load__(self) -> Any: try: import pandas except ImportError as err: raise MissingDependencyError(PANDAS_INSTRUCTIONS) from err return pandas if not TYPE_CHECKING: pandas = PandasProxy() ================================================ FILE: src/openai/_extras/sounddevice_proxy.py ================================================ from __future__ import annotations from typing import TYPE_CHECKING, Any from typing_extensions import override from .._utils import LazyProxy from ._common import MissingDependencyError, format_instructions if TYPE_CHECKING: import sounddevice as sounddevice # type: ignore SOUNDDEVICE_INSTRUCTIONS = format_instructions(library="sounddevice", extra="voice_helpers") class SounddeviceProxy(LazyProxy[Any]): @override def __load__(self) -> Any: try: import sounddevice # type: ignore except ImportError as err: raise MissingDependencyError(SOUNDDEVICE_INSTRUCTIONS) from err return sounddevice if not TYPE_CHECKING: sounddevice = SounddeviceProxy() ================================================ FILE: src/openai/_files.py ================================================ from __future__ import annotations import io import os import pathlib from typing import overload from typing_extensions import TypeGuard import anyio from ._types import ( FileTypes, FileContent, RequestFiles, HttpxFileTypes, Base64FileInput, HttpxFileContent, HttpxRequestFiles, ) from ._utils import is_tuple_t, is_mapping_t, is_sequence_t def is_base64_file_input(obj: object) -> TypeGuard[Base64FileInput]: return isinstance(obj, io.IOBase) or isinstance(obj, os.PathLike) def is_file_content(obj: object) -> TypeGuard[FileContent]: return ( isinstance(obj, bytes) or isinstance(obj, tuple) or isinstance(obj, io.IOBase) or isinstance(obj, os.PathLike) ) def assert_is_file_content(obj: object, *, key: str | None = None) -> None: if not is_file_content(obj): prefix = f"Expected entry at `{key}`" if key is not None else f"Expected file input `{obj!r}`" raise RuntimeError( f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/openai/openai-python/tree/main#file-uploads" ) from None @overload def to_httpx_files(files: None) -> None: ... @overload def to_httpx_files(files: RequestFiles) -> HttpxRequestFiles: ... def to_httpx_files(files: RequestFiles | None) -> HttpxRequestFiles | None: if files is None: return None if is_mapping_t(files): files = {key: _transform_file(file) for key, file in files.items()} elif is_sequence_t(files): files = [(key, _transform_file(file)) for key, file in files] else: raise TypeError(f"Unexpected file type input {type(files)}, expected mapping or sequence") return files def _transform_file(file: FileTypes) -> HttpxFileTypes: if is_file_content(file): if isinstance(file, os.PathLike): path = pathlib.Path(file) return (path.name, path.read_bytes()) return file if is_tuple_t(file): return (file[0], read_file_content(file[1]), *file[2:]) raise TypeError(f"Expected file types input to be a FileContent type or to be a tuple") def read_file_content(file: FileContent) -> HttpxFileContent: if isinstance(file, os.PathLike): return pathlib.Path(file).read_bytes() return file @overload async def async_to_httpx_files(files: None) -> None: ... @overload async def async_to_httpx_files(files: RequestFiles) -> HttpxRequestFiles: ... async def async_to_httpx_files(files: RequestFiles | None) -> HttpxRequestFiles | None: if files is None: return None if is_mapping_t(files): files = {key: await _async_transform_file(file) for key, file in files.items()} elif is_sequence_t(files): files = [(key, await _async_transform_file(file)) for key, file in files] else: raise TypeError("Unexpected file type input {type(files)}, expected mapping or sequence") return files async def _async_transform_file(file: FileTypes) -> HttpxFileTypes: if is_file_content(file): if isinstance(file, os.PathLike): path = anyio.Path(file) return (path.name, await path.read_bytes()) return file if is_tuple_t(file): return (file[0], await async_read_file_content(file[1]), *file[2:]) raise TypeError(f"Expected file types input to be a FileContent type or to be a tuple") async def async_read_file_content(file: FileContent) -> HttpxFileContent: if isinstance(file, os.PathLike): return await anyio.Path(file).read_bytes() return file ================================================ FILE: src/openai/_legacy_response.py ================================================ from __future__ import annotations import os import inspect import logging import datetime import functools from typing import ( TYPE_CHECKING, Any, Union, Generic, TypeVar, Callable, Iterator, AsyncIterator, cast, overload, ) from typing_extensions import Awaitable, ParamSpec, override, deprecated, get_origin import anyio import httpx import pydantic from ._types import NoneType from ._utils import is_given, extract_type_arg, is_annotated_type, is_type_alias_type from ._models import BaseModel, is_basemodel, add_request_id from ._constants import RAW_RESPONSE_HEADER from ._streaming import Stream, AsyncStream, is_stream_class_type, extract_stream_chunk_type from ._exceptions import APIResponseValidationError if TYPE_CHECKING: from ._models import FinalRequestOptions from ._base_client import BaseClient P = ParamSpec("P") R = TypeVar("R") _T = TypeVar("_T") log: logging.Logger = logging.getLogger(__name__) class LegacyAPIResponse(Generic[R]): """This is a legacy class as it will be replaced by `APIResponse` and `AsyncAPIResponse` in the `_response.py` file in the next major release. For the sync client this will mostly be the same with the exception of `content` & `text` will be methods instead of properties. In the async client, all methods will be async. A migration script will be provided & the migration in general should be smooth. """ _cast_to: type[R] _client: BaseClient[Any, Any] _parsed_by_type: dict[type[Any], Any] _stream: bool _stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None _options: FinalRequestOptions http_response: httpx.Response retries_taken: int """The number of retries made. If no retries happened this will be `0`""" def __init__( self, *, raw: httpx.Response, cast_to: type[R], client: BaseClient[Any, Any], stream: bool, stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None, options: FinalRequestOptions, retries_taken: int = 0, ) -> None: self._cast_to = cast_to self._client = client self._parsed_by_type = {} self._stream = stream self._stream_cls = stream_cls self._options = options self.http_response = raw self.retries_taken = retries_taken @property def request_id(self) -> str | None: return self.http_response.headers.get("x-request-id") # type: ignore[no-any-return] @overload def parse(self, *, to: type[_T]) -> _T: ... @overload def parse(self) -> R: ... def parse(self, *, to: type[_T] | None = None) -> R | _T: """Returns the rich python representation of this response's data. NOTE: For the async client: this will become a coroutine in the next major version. For lower-level control, see `.read()`, `.json()`, `.iter_bytes()`. You can customise the type that the response is parsed into through the `to` argument, e.g. ```py from openai import BaseModel class MyModel(BaseModel): foo: str obj = response.parse(to=MyModel) print(obj.foo) ``` We support parsing: - `BaseModel` - `dict` - `list` - `Union` - `str` - `int` - `float` - `httpx.Response` """ cache_key = to if to is not None else self._cast_to cached = self._parsed_by_type.get(cache_key) if cached is not None: return cached # type: ignore[no-any-return] parsed = self._parse(to=to) if is_given(self._options.post_parser): parsed = self._options.post_parser(parsed) if isinstance(parsed, BaseModel): add_request_id(parsed, self.request_id) self._parsed_by_type[cache_key] = parsed return cast(R, parsed) @property def headers(self) -> httpx.Headers: return self.http_response.headers @property def http_request(self) -> httpx.Request: return self.http_response.request @property def status_code(self) -> int: return self.http_response.status_code @property def url(self) -> httpx.URL: return self.http_response.url @property def method(self) -> str: return self.http_request.method @property def content(self) -> bytes: """Return the binary response content. NOTE: this will be removed in favour of `.read()` in the next major version. """ return self.http_response.content @property def text(self) -> str: """Return the decoded response content. NOTE: this will be turned into a method in the next major version. """ return self.http_response.text @property def http_version(self) -> str: return self.http_response.http_version @property def is_closed(self) -> bool: return self.http_response.is_closed @property def elapsed(self) -> datetime.timedelta: """The time taken for the complete request/response cycle to complete.""" return self.http_response.elapsed def _parse(self, *, to: type[_T] | None = None) -> R | _T: cast_to = to if to is not None else self._cast_to # unwrap `TypeAlias('Name', T)` -> `T` if is_type_alias_type(cast_to): cast_to = cast_to.__value__ # type: ignore[unreachable] # unwrap `Annotated[T, ...]` -> `T` if cast_to and is_annotated_type(cast_to): cast_to = extract_type_arg(cast_to, 0) origin = get_origin(cast_to) or cast_to if self._stream: if to: if not is_stream_class_type(to): raise TypeError(f"Expected custom parse type to be a subclass of {Stream} or {AsyncStream}") return cast( _T, to( cast_to=extract_stream_chunk_type( to, failure_message="Expected custom stream type to be passed with a type argument, e.g. Stream[ChunkType]", ), response=self.http_response, client=cast(Any, self._client), options=self._options, ), ) if self._stream_cls: return cast( R, self._stream_cls( cast_to=extract_stream_chunk_type(self._stream_cls), response=self.http_response, client=cast(Any, self._client), options=self._options, ), ) stream_cls = cast("type[Stream[Any]] | type[AsyncStream[Any]] | None", self._client._default_stream_cls) if stream_cls is None: raise MissingStreamClassError() return cast( R, stream_cls( cast_to=cast_to, response=self.http_response, client=cast(Any, self._client), options=self._options, ), ) if cast_to is NoneType: return cast(R, None) response = self.http_response if cast_to == str: return cast(R, response.text) if cast_to == int: return cast(R, int(response.text)) if cast_to == float: return cast(R, float(response.text)) if cast_to == bool: return cast(R, response.text.lower() == "true") if inspect.isclass(origin) and issubclass(origin, HttpxBinaryResponseContent): return cast(R, cast_to(response)) # type: ignore if origin == LegacyAPIResponse: raise RuntimeError("Unexpected state - cast_to is `APIResponse`") if inspect.isclass( origin # pyright: ignore[reportUnknownArgumentType] ) and issubclass(origin, httpx.Response): # Because of the invariance of our ResponseT TypeVar, users can subclass httpx.Response # and pass that class to our request functions. We cannot change the variance to be either # covariant or contravariant as that makes our usage of ResponseT illegal. We could construct # the response class ourselves but that is something that should be supported directly in httpx # as it would be easy to incorrectly construct the Response object due to the multitude of arguments. if cast_to != httpx.Response: raise ValueError(f"Subclasses of httpx.Response cannot be passed to `cast_to`") return cast(R, response) if ( inspect.isclass( origin # pyright: ignore[reportUnknownArgumentType] ) and not issubclass(origin, BaseModel) and issubclass(origin, pydantic.BaseModel) ): raise TypeError("Pydantic models must subclass our base model type, e.g. `from openai import BaseModel`") if ( cast_to is not object and not origin is list and not origin is dict and not origin is Union and not issubclass(origin, BaseModel) ): raise RuntimeError( f"Unsupported type, expected {cast_to} to be a subclass of {BaseModel}, {dict}, {list}, {Union}, {NoneType}, {str} or {httpx.Response}." ) # split is required to handle cases where additional information is included # in the response, e.g. application/json; charset=utf-8 content_type, *_ = response.headers.get("content-type", "*").split(";") if not content_type.endswith("json"): if is_basemodel(cast_to): try: data = response.json() except Exception as exc: log.debug("Could not read JSON from response data due to %s - %s", type(exc), exc) else: return self._client._process_response_data( data=data, cast_to=cast_to, # type: ignore response=response, ) if self._client._strict_response_validation: raise APIResponseValidationError( response=response, message=f"Expected Content-Type response header to be `application/json` but received `{content_type}` instead.", body=response.text, ) # If the API responds with content that isn't JSON then we just return # the (decoded) text without performing any parsing so that you can still # handle the response however you need to. return response.text # type: ignore data = response.json() return self._client._process_response_data( data=data, cast_to=cast_to, # type: ignore response=response, ) @override def __repr__(self) -> str: return f"" class MissingStreamClassError(TypeError): def __init__(self) -> None: super().__init__( "The `stream` argument was set to `True` but the `stream_cls` argument was not given. See `openai._streaming` for reference", ) def to_raw_response_wrapper(func: Callable[P, R]) -> Callable[P, LegacyAPIResponse[R]]: """Higher order function that takes one of our bound API methods and wraps it to support returning the raw `APIResponse` object directly. """ @functools.wraps(func) def wrapped(*args: P.args, **kwargs: P.kwargs) -> LegacyAPIResponse[R]: extra_headers: dict[str, str] = {**(cast(Any, kwargs.get("extra_headers")) or {})} extra_headers[RAW_RESPONSE_HEADER] = "true" kwargs["extra_headers"] = extra_headers return cast(LegacyAPIResponse[R], func(*args, **kwargs)) return wrapped def async_to_raw_response_wrapper(func: Callable[P, Awaitable[R]]) -> Callable[P, Awaitable[LegacyAPIResponse[R]]]: """Higher order function that takes one of our bound API methods and wraps it to support returning the raw `APIResponse` object directly. """ @functools.wraps(func) async def wrapped(*args: P.args, **kwargs: P.kwargs) -> LegacyAPIResponse[R]: extra_headers: dict[str, str] = {**(cast(Any, kwargs.get("extra_headers")) or {})} extra_headers[RAW_RESPONSE_HEADER] = "true" kwargs["extra_headers"] = extra_headers return cast(LegacyAPIResponse[R], await func(*args, **kwargs)) return wrapped class HttpxBinaryResponseContent: response: httpx.Response def __init__(self, response: httpx.Response) -> None: self.response = response @property def content(self) -> bytes: return self.response.content @property def text(self) -> str: return self.response.text @property def encoding(self) -> str | None: return self.response.encoding @property def charset_encoding(self) -> str | None: return self.response.charset_encoding def json(self, **kwargs: Any) -> Any: return self.response.json(**kwargs) def read(self) -> bytes: return self.response.read() def iter_bytes(self, chunk_size: int | None = None) -> Iterator[bytes]: return self.response.iter_bytes(chunk_size) def iter_text(self, chunk_size: int | None = None) -> Iterator[str]: return self.response.iter_text(chunk_size) def iter_lines(self) -> Iterator[str]: return self.response.iter_lines() def iter_raw(self, chunk_size: int | None = None) -> Iterator[bytes]: return self.response.iter_raw(chunk_size) def write_to_file( self, file: str | os.PathLike[str], ) -> None: """Write the output to the given file. Accepts a filename or any path-like object, e.g. pathlib.Path Note: if you want to stream the data to the file instead of writing all at once then you should use `.with_streaming_response` when making the API request, e.g. `client.with_streaming_response.foo().stream_to_file('my_filename.txt')` """ with open(file, mode="wb") as f: for data in self.response.iter_bytes(): f.write(data) @deprecated( "Due to a bug, this method doesn't actually stream the response content, `.with_streaming_response.method()` should be used instead" ) def stream_to_file( self, file: str | os.PathLike[str], *, chunk_size: int | None = None, ) -> None: with open(file, mode="wb") as f: for data in self.response.iter_bytes(chunk_size): f.write(data) def close(self) -> None: return self.response.close() async def aread(self) -> bytes: return await self.response.aread() async def aiter_bytes(self, chunk_size: int | None = None) -> AsyncIterator[bytes]: return self.response.aiter_bytes(chunk_size) async def aiter_text(self, chunk_size: int | None = None) -> AsyncIterator[str]: return self.response.aiter_text(chunk_size) async def aiter_lines(self) -> AsyncIterator[str]: return self.response.aiter_lines() async def aiter_raw(self, chunk_size: int | None = None) -> AsyncIterator[bytes]: return self.response.aiter_raw(chunk_size) @deprecated( "Due to a bug, this method doesn't actually stream the response content, `.with_streaming_response.method()` should be used instead" ) async def astream_to_file( self, file: str | os.PathLike[str], *, chunk_size: int | None = None, ) -> None: path = anyio.Path(file) async with await path.open(mode="wb") as f: async for data in self.response.aiter_bytes(chunk_size): await f.write(data) async def aclose(self) -> None: return await self.response.aclose() ================================================ FILE: src/openai/_models.py ================================================ from __future__ import annotations import os import inspect import weakref from typing import ( IO, TYPE_CHECKING, Any, Type, Tuple, Union, Generic, TypeVar, Callable, Iterable, Optional, AsyncIterable, cast, ) from datetime import date, datetime from typing_extensions import ( List, Unpack, Literal, ClassVar, Protocol, Required, Sequence, ParamSpec, TypedDict, TypeGuard, final, override, runtime_checkable, ) import pydantic from pydantic.fields import FieldInfo from ._types import ( Body, IncEx, Query, ModelT, Headers, Timeout, NotGiven, AnyMapping, HttpxRequestFiles, ) from ._utils import ( PropertyInfo, is_list, is_given, json_safe, lru_cache, is_mapping, parse_date, coerce_boolean, parse_datetime, strip_not_given, extract_type_arg, is_annotated_type, is_type_alias_type, strip_annotated_type, ) from ._compat import ( PYDANTIC_V1, ConfigDict, GenericModel as BaseGenericModel, get_args, is_union, parse_obj, get_origin, is_literal_type, get_model_config, get_model_fields, field_get_default, ) from ._constants import RAW_RESPONSE_HEADER if TYPE_CHECKING: from pydantic_core.core_schema import ModelField, ModelSchema, LiteralSchema, ModelFieldsSchema __all__ = ["BaseModel", "GenericModel"] _T = TypeVar("_T") _BaseModelT = TypeVar("_BaseModelT", bound="BaseModel") P = ParamSpec("P") ReprArgs = Sequence[Tuple[Optional[str], Any]] @runtime_checkable class _ConfigProtocol(Protocol): allow_population_by_field_name: bool class BaseModel(pydantic.BaseModel): if PYDANTIC_V1: @property @override def model_fields_set(self) -> set[str]: # a forwards-compat shim for pydantic v2 return self.__fields_set__ # type: ignore class Config(pydantic.BaseConfig): # pyright: ignore[reportDeprecated] extra: Any = pydantic.Extra.allow # type: ignore @override def __repr_args__(self) -> ReprArgs: # we don't want these attributes to be included when something like `rich.print` is used return [arg for arg in super().__repr_args__() if arg[0] not in {"_request_id", "__exclude_fields__"}] else: model_config: ClassVar[ConfigDict] = ConfigDict( extra="allow", defer_build=coerce_boolean(os.environ.get("DEFER_PYDANTIC_BUILD", "true")) ) if TYPE_CHECKING: _request_id: Optional[str] = None """The ID of the request, returned via the X-Request-ID header. Useful for debugging requests and reporting issues to OpenAI. This will **only** be set for the top-level response object, it will not be defined for nested objects. For example: ```py completion = await client.chat.completions.create(...) completion._request_id # req_id_xxx completion.usage._request_id # raises `AttributeError` ``` Note: unlike other properties that use an `_` prefix, this property *is* public. Unless documented otherwise, all other `_` prefix properties, methods and modules are *private*. """ def to_dict( self, *, mode: Literal["json", "python"] = "python", use_api_names: bool = True, exclude_unset: bool = True, exclude_defaults: bool = False, exclude_none: bool = False, warnings: bool = True, ) -> dict[str, object]: """Recursively generate a dictionary representation of the model, optionally specifying which fields to include or exclude. By default, fields that were not set by the API will not be included, and keys will match the API response, *not* the property names from the model. For example, if the API responds with `"fooBar": true` but we've defined a `foo_bar: bool` property, the output will use the `"fooBar"` key (unless `use_api_names=False` is passed). Args: mode: If mode is 'json', the dictionary will only contain JSON serializable types. e.g. `datetime` will be turned into a string, `"2024-3-22T18:11:19.117000Z"`. If mode is 'python', the dictionary may contain any Python objects. e.g. `datetime(2024, 3, 22)` use_api_names: Whether to use the key that the API responded with or the property name. Defaults to `True`. exclude_unset: Whether to exclude fields that have not been explicitly set. exclude_defaults: Whether to exclude fields that are set to their default value from the output. exclude_none: Whether to exclude fields that have a value of `None` from the output. warnings: Whether to log warnings when invalid fields are encountered. This is only supported in Pydantic v2. """ return self.model_dump( mode=mode, by_alias=use_api_names, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, warnings=warnings, ) def to_json( self, *, indent: int | None = 2, use_api_names: bool = True, exclude_unset: bool = True, exclude_defaults: bool = False, exclude_none: bool = False, warnings: bool = True, ) -> str: """Generates a JSON string representing this model as it would be received from or sent to the API (but with indentation). By default, fields that were not set by the API will not be included, and keys will match the API response, *not* the property names from the model. For example, if the API responds with `"fooBar": true` but we've defined a `foo_bar: bool` property, the output will use the `"fooBar"` key (unless `use_api_names=False` is passed). Args: indent: Indentation to use in the JSON output. If `None` is passed, the output will be compact. Defaults to `2` use_api_names: Whether to use the key that the API responded with or the property name. Defaults to `True`. exclude_unset: Whether to exclude fields that have not been explicitly set. exclude_defaults: Whether to exclude fields that have the default value. exclude_none: Whether to exclude fields that have a value of `None`. warnings: Whether to show any warnings that occurred during serialization. This is only supported in Pydantic v2. """ return self.model_dump_json( indent=indent, by_alias=use_api_names, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, warnings=warnings, ) @override def __str__(self) -> str: # mypy complains about an invalid self arg return f"{self.__repr_name__()}({self.__repr_str__(', ')})" # type: ignore[misc] # Override the 'construct' method in a way that supports recursive parsing without validation. # Based on https://github.com/samuelcolvin/pydantic/issues/1168#issuecomment-817742836. @classmethod @override def construct( # pyright: ignore[reportIncompatibleMethodOverride] __cls: Type[ModelT], _fields_set: set[str] | None = None, **values: object, ) -> ModelT: m = __cls.__new__(__cls) fields_values: dict[str, object] = {} config = get_model_config(__cls) populate_by_name = ( config.allow_population_by_field_name if isinstance(config, _ConfigProtocol) else config.get("populate_by_name") ) if _fields_set is None: _fields_set = set() model_fields = get_model_fields(__cls) for name, field in model_fields.items(): key = field.alias if key is None or (key not in values and populate_by_name): key = name if key in values: fields_values[name] = _construct_field(value=values[key], field=field, key=key) _fields_set.add(name) else: fields_values[name] = field_get_default(field) extra_field_type = _get_extra_fields_type(__cls) _extra = {} for key, value in values.items(): if key not in model_fields: parsed = construct_type(value=value, type_=extra_field_type) if extra_field_type is not None else value if PYDANTIC_V1: _fields_set.add(key) fields_values[key] = parsed else: _extra[key] = parsed object.__setattr__(m, "__dict__", fields_values) if PYDANTIC_V1: # init_private_attributes() does not exist in v2 m._init_private_attributes() # type: ignore # copied from Pydantic v1's `construct()` method object.__setattr__(m, "__fields_set__", _fields_set) else: # these properties are copied from Pydantic's `model_construct()` method object.__setattr__(m, "__pydantic_private__", None) object.__setattr__(m, "__pydantic_extra__", _extra) object.__setattr__(m, "__pydantic_fields_set__", _fields_set) return m if not TYPE_CHECKING: # type checkers incorrectly complain about this assignment # because the type signatures are technically different # although not in practice model_construct = construct if PYDANTIC_V1: # we define aliases for some of the new pydantic v2 methods so # that we can just document these methods without having to specify # a specific pydantic version as some users may not know which # pydantic version they are currently using @override def model_dump( self, *, mode: Literal["json", "python"] | str = "python", include: IncEx | None = None, exclude: IncEx | None = None, context: Any | None = None, by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, exclude_computed_fields: bool = False, round_trip: bool = False, warnings: bool | Literal["none", "warn", "error"] = True, fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False, ) -> dict[str, Any]: """Usage docs: https://docs.pydantic.dev/2.4/concepts/serialization/#modelmodel_dump Generate a dictionary representation of the model, optionally specifying which fields to include or exclude. Args: mode: The mode in which `to_python` should run. If mode is 'json', the output will only contain JSON serializable types. If mode is 'python', the output may contain non-JSON-serializable Python objects. include: A set of fields to include in the output. exclude: A set of fields to exclude from the output. context: Additional context to pass to the serializer. by_alias: Whether to use the field's alias in the dictionary key if defined. exclude_unset: Whether to exclude fields that have not been explicitly set. exclude_defaults: Whether to exclude fields that are set to their default value. exclude_none: Whether to exclude fields that have a value of `None`. exclude_computed_fields: Whether to exclude computed fields. While this can be useful for round-tripping, it is usually recommended to use the dedicated `round_trip` parameter instead. round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T]. warnings: How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors, "error" raises a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError]. fallback: A function to call when an unknown value is encountered. If not provided, a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError] error is raised. serialize_as_any: Whether to serialize fields with duck-typing serialization behavior. Returns: A dictionary representation of the model. """ if mode not in {"json", "python"}: raise ValueError("mode must be either 'json' or 'python'") if round_trip != False: raise ValueError("round_trip is only supported in Pydantic v2") if warnings != True: raise ValueError("warnings is only supported in Pydantic v2") if context is not None: raise ValueError("context is only supported in Pydantic v2") if serialize_as_any != False: raise ValueError("serialize_as_any is only supported in Pydantic v2") if fallback is not None: raise ValueError("fallback is only supported in Pydantic v2") if exclude_computed_fields != False: raise ValueError("exclude_computed_fields is only supported in Pydantic v2") dumped = super().dict( # pyright: ignore[reportDeprecated] include=include, exclude=exclude, by_alias=by_alias if by_alias is not None else False, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, ) return cast("dict[str, Any]", json_safe(dumped)) if mode == "json" else dumped @override def model_dump_json( self, *, indent: int | None = None, ensure_ascii: bool = False, include: IncEx | None = None, exclude: IncEx | None = None, context: Any | None = None, by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, exclude_computed_fields: bool = False, round_trip: bool = False, warnings: bool | Literal["none", "warn", "error"] = True, fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False, ) -> str: """Usage docs: https://docs.pydantic.dev/2.4/concepts/serialization/#modelmodel_dump_json Generates a JSON representation of the model using Pydantic's `to_json` method. Args: indent: Indentation to use in the JSON output. If None is passed, the output will be compact. include: Field(s) to include in the JSON output. Can take either a string or set of strings. exclude: Field(s) to exclude from the JSON output. Can take either a string or set of strings. by_alias: Whether to serialize using field aliases. exclude_unset: Whether to exclude fields that have not been explicitly set. exclude_defaults: Whether to exclude fields that have the default value. exclude_none: Whether to exclude fields that have a value of `None`. round_trip: Whether to use serialization/deserialization between JSON and class instance. warnings: Whether to show any warnings that occurred during serialization. Returns: A JSON string representation of the model. """ if round_trip != False: raise ValueError("round_trip is only supported in Pydantic v2") if warnings != True: raise ValueError("warnings is only supported in Pydantic v2") if context is not None: raise ValueError("context is only supported in Pydantic v2") if serialize_as_any != False: raise ValueError("serialize_as_any is only supported in Pydantic v2") if fallback is not None: raise ValueError("fallback is only supported in Pydantic v2") if ensure_ascii != False: raise ValueError("ensure_ascii is only supported in Pydantic v2") if exclude_computed_fields != False: raise ValueError("exclude_computed_fields is only supported in Pydantic v2") return super().json( # type: ignore[reportDeprecated] indent=indent, include=include, exclude=exclude, by_alias=by_alias if by_alias is not None else False, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, ) def _construct_field(value: object, field: FieldInfo, key: str) -> object: if value is None: return field_get_default(field) if PYDANTIC_V1: type_ = cast(type, field.outer_type_) # type: ignore else: type_ = field.annotation # type: ignore if type_ is None: raise RuntimeError(f"Unexpected field type is None for {key}") return construct_type(value=value, type_=type_, metadata=getattr(field, "metadata", None)) def _get_extra_fields_type(cls: type[pydantic.BaseModel]) -> type | None: if PYDANTIC_V1: # TODO return None schema = cls.__pydantic_core_schema__ if schema["type"] == "model": fields = schema["schema"] if fields["type"] == "model-fields": extras = fields.get("extras_schema") if extras and "cls" in extras: # mypy can't narrow the type return extras["cls"] # type: ignore[no-any-return] return None def is_basemodel(type_: type) -> bool: """Returns whether or not the given type is either a `BaseModel` or a union of `BaseModel`""" if is_union(type_): for variant in get_args(type_): if is_basemodel(variant): return True return False return is_basemodel_type(type_) def is_basemodel_type(type_: type) -> TypeGuard[type[BaseModel] | type[GenericModel]]: origin = get_origin(type_) or type_ if not inspect.isclass(origin): return False return issubclass(origin, BaseModel) or issubclass(origin, GenericModel) def build( base_model_cls: Callable[P, _BaseModelT], *args: P.args, **kwargs: P.kwargs, ) -> _BaseModelT: """Construct a BaseModel class without validation. This is useful for cases where you need to instantiate a `BaseModel` from an API response as this provides type-safe params which isn't supported by helpers like `construct_type()`. ```py build(MyModel, my_field_a="foo", my_field_b=123) ``` """ if args: raise TypeError( "Received positional arguments which are not supported; Keyword arguments must be used instead", ) return cast(_BaseModelT, construct_type(type_=base_model_cls, value=kwargs)) def construct_type_unchecked(*, value: object, type_: type[_T]) -> _T: """Loose coercion to the expected type with construction of nested values. Note: the returned value from this function is not guaranteed to match the given type. """ return cast(_T, construct_type(value=value, type_=type_)) def construct_type(*, value: object, type_: object, metadata: Optional[List[Any]] = None) -> object: """Loose coercion to the expected type with construction of nested values. If the given value does not match the expected type then it is returned as-is. """ # store a reference to the original type we were given before we extract any inner # types so that we can properly resolve forward references in `TypeAliasType` annotations original_type = None # we allow `object` as the input type because otherwise, passing things like # `Literal['value']` will be reported as a type error by type checkers type_ = cast("type[object]", type_) if is_type_alias_type(type_): original_type = type_ # type: ignore[unreachable] type_ = type_.__value__ # type: ignore[unreachable] # unwrap `Annotated[T, ...]` -> `T` if metadata is not None and len(metadata) > 0: meta: tuple[Any, ...] = tuple(metadata) elif is_annotated_type(type_): meta = get_args(type_)[1:] type_ = extract_type_arg(type_, 0) else: meta = tuple() # we need to use the origin class for any types that are subscripted generics # e.g. Dict[str, object] origin = get_origin(type_) or type_ args = get_args(type_) if is_union(origin): try: return validate_type(type_=cast("type[object]", original_type or type_), value=value) except Exception: pass # if the type is a discriminated union then we want to construct the right variant # in the union, even if the data doesn't match exactly, otherwise we'd break code # that relies on the constructed class types, e.g. # # class FooType: # kind: Literal['foo'] # value: str # # class BarType: # kind: Literal['bar'] # value: int # # without this block, if the data we get is something like `{'kind': 'bar', 'value': 'foo'}` then # we'd end up constructing `FooType` when it should be `BarType`. discriminator = _build_discriminated_union_meta(union=type_, meta_annotations=meta) if discriminator and is_mapping(value): variant_value = value.get(discriminator.field_alias_from or discriminator.field_name) if variant_value and isinstance(variant_value, str): variant_type = discriminator.mapping.get(variant_value) if variant_type: return construct_type(type_=variant_type, value=value) # if the data is not valid, use the first variant that doesn't fail while deserializing for variant in args: try: return construct_type(value=value, type_=variant) except Exception: continue raise RuntimeError(f"Could not convert data into a valid instance of {type_}") if origin == dict: if not is_mapping(value): return value _, items_type = get_args(type_) # Dict[_, items_type] return {key: construct_type(value=item, type_=items_type) for key, item in value.items()} if ( not is_literal_type(type_) and inspect.isclass(origin) and (issubclass(origin, BaseModel) or issubclass(origin, GenericModel)) ): if is_list(value): return [cast(Any, type_).construct(**entry) if is_mapping(entry) else entry for entry in value] if is_mapping(value): if issubclass(type_, BaseModel): return type_.construct(**value) # type: ignore[arg-type] return cast(Any, type_).construct(**value) if origin == list: if not is_list(value): return value inner_type = args[0] # List[inner_type] return [construct_type(value=entry, type_=inner_type) for entry in value] if origin == float: if isinstance(value, int): coerced = float(value) if coerced != value: return value return coerced return value if type_ == datetime: try: return parse_datetime(value) # type: ignore except Exception: return value if type_ == date: try: return parse_date(value) # type: ignore except Exception: return value return value @runtime_checkable class CachedDiscriminatorType(Protocol): __discriminator__: DiscriminatorDetails DISCRIMINATOR_CACHE: weakref.WeakKeyDictionary[type, DiscriminatorDetails] = weakref.WeakKeyDictionary() class DiscriminatorDetails: field_name: str """The name of the discriminator field in the variant class, e.g. ```py class Foo(BaseModel): type: Literal['foo'] ``` Will result in field_name='type' """ field_alias_from: str | None """The name of the discriminator field in the API response, e.g. ```py class Foo(BaseModel): type: Literal['foo'] = Field(alias='type_from_api') ``` Will result in field_alias_from='type_from_api' """ mapping: dict[str, type] """Mapping of discriminator value to variant type, e.g. {'foo': FooVariant, 'bar': BarVariant} """ def __init__( self, *, mapping: dict[str, type], discriminator_field: str, discriminator_alias: str | None, ) -> None: self.mapping = mapping self.field_name = discriminator_field self.field_alias_from = discriminator_alias def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any, ...]) -> DiscriminatorDetails | None: cached = DISCRIMINATOR_CACHE.get(union) if cached is not None: return cached discriminator_field_name: str | None = None for annotation in meta_annotations: if isinstance(annotation, PropertyInfo) and annotation.discriminator is not None: discriminator_field_name = annotation.discriminator break if not discriminator_field_name: return None mapping: dict[str, type] = {} discriminator_alias: str | None = None for variant in get_args(union): variant = strip_annotated_type(variant) if is_basemodel_type(variant): if PYDANTIC_V1: field_info = cast("dict[str, FieldInfo]", variant.__fields__).get(discriminator_field_name) # pyright: ignore[reportDeprecated, reportUnnecessaryCast] if not field_info: continue # Note: if one variant defines an alias then they all should discriminator_alias = field_info.alias if (annotation := getattr(field_info, "annotation", None)) and is_literal_type(annotation): for entry in get_args(annotation): if isinstance(entry, str): mapping[entry] = variant else: field = _extract_field_schema_pv2(variant, discriminator_field_name) if not field: continue # Note: if one variant defines an alias then they all should discriminator_alias = field.get("serialization_alias") field_schema = field["schema"] if field_schema["type"] == "literal": for entry in cast("LiteralSchema", field_schema)["expected"]: if isinstance(entry, str): mapping[entry] = variant if not mapping: return None details = DiscriminatorDetails( mapping=mapping, discriminator_field=discriminator_field_name, discriminator_alias=discriminator_alias, ) DISCRIMINATOR_CACHE.setdefault(union, details) return details def _extract_field_schema_pv2(model: type[BaseModel], field_name: str) -> ModelField | None: schema = model.__pydantic_core_schema__ if schema["type"] == "definitions": schema = schema["schema"] if schema["type"] != "model": return None schema = cast("ModelSchema", schema) fields_schema = schema["schema"] if fields_schema["type"] != "model-fields": return None fields_schema = cast("ModelFieldsSchema", fields_schema) field = fields_schema["fields"].get(field_name) if not field: return None return cast("ModelField", field) # pyright: ignore[reportUnnecessaryCast] def validate_type(*, type_: type[_T], value: object) -> _T: """Strict validation that the given value matches the expected type""" if inspect.isclass(type_) and issubclass(type_, pydantic.BaseModel): return cast(_T, parse_obj(type_, value)) return cast(_T, _validate_non_model_type(type_=type_, value=value)) def set_pydantic_config(typ: Any, config: pydantic.ConfigDict) -> None: """Add a pydantic config for the given type. Note: this is a no-op on Pydantic v1. """ setattr(typ, "__pydantic_config__", config) # noqa: B010 def add_request_id(obj: BaseModel, request_id: str | None) -> None: obj._request_id = request_id # in Pydantic v1, using setattr like we do above causes the attribute # to be included when serializing the model which we don't want in this # case so we need to explicitly exclude it if PYDANTIC_V1: try: exclude_fields = obj.__exclude_fields__ # type: ignore except AttributeError: cast(Any, obj).__exclude_fields__ = {"_request_id", "__exclude_fields__"} else: cast(Any, obj).__exclude_fields__ = {*(exclude_fields or {}), "_request_id", "__exclude_fields__"} # our use of subclassing here causes weirdness for type checkers, # so we just pretend that we don't subclass if TYPE_CHECKING: GenericModel = BaseModel else: class GenericModel(BaseGenericModel, BaseModel): pass if not PYDANTIC_V1: from pydantic import TypeAdapter as _TypeAdapter _CachedTypeAdapter = cast("TypeAdapter[object]", lru_cache(maxsize=None)(_TypeAdapter)) if TYPE_CHECKING: from pydantic import TypeAdapter else: TypeAdapter = _CachedTypeAdapter def _validate_non_model_type(*, type_: type[_T], value: object) -> _T: return TypeAdapter(type_).validate_python(value) elif not TYPE_CHECKING: # TODO: condition is weird class RootModel(GenericModel, Generic[_T]): """Used as a placeholder to easily convert runtime types to a Pydantic format to provide validation. For example: ```py validated = RootModel[int](__root__="5").__root__ # validated: 5 ``` """ __root__: _T def _validate_non_model_type(*, type_: type[_T], value: object) -> _T: model = _create_pydantic_model(type_).validate(value) return cast(_T, model.__root__) def _create_pydantic_model(type_: _T) -> Type[RootModel[_T]]: return RootModel[type_] # type: ignore class FinalRequestOptionsInput(TypedDict, total=False): method: Required[str] url: Required[str] params: Query headers: Headers max_retries: int timeout: float | Timeout | None files: HttpxRequestFiles | None idempotency_key: str content: Union[bytes, bytearray, IO[bytes], Iterable[bytes], AsyncIterable[bytes], None] json_data: Body extra_json: AnyMapping follow_redirects: bool synthesize_event_and_data: bool @final class FinalRequestOptions(pydantic.BaseModel): method: str url: str params: Query = {} headers: Union[Headers, NotGiven] = NotGiven() max_retries: Union[int, NotGiven] = NotGiven() timeout: Union[float, Timeout, None, NotGiven] = NotGiven() files: Union[HttpxRequestFiles, None] = None idempotency_key: Union[str, None] = None post_parser: Union[Callable[[Any], Any], NotGiven] = NotGiven() follow_redirects: Union[bool, None] = None synthesize_event_and_data: Optional[bool] = None content: Union[bytes, bytearray, IO[bytes], Iterable[bytes], AsyncIterable[bytes], None] = None # It should be noted that we cannot use `json` here as that would override # a BaseModel method in an incompatible fashion. json_data: Union[Body, None] = None extra_json: Union[AnyMapping, None] = None if PYDANTIC_V1: class Config(pydantic.BaseConfig): # pyright: ignore[reportDeprecated] arbitrary_types_allowed: bool = True else: model_config: ClassVar[ConfigDict] = ConfigDict(arbitrary_types_allowed=True) def get_max_retries(self, max_retries: int) -> int: if isinstance(self.max_retries, NotGiven): return max_retries return self.max_retries def _strip_raw_response_header(self) -> None: if not is_given(self.headers): return if self.headers.get(RAW_RESPONSE_HEADER): self.headers = {**self.headers} self.headers.pop(RAW_RESPONSE_HEADER) # override the `construct` method so that we can run custom transformations. # this is necessary as we don't want to do any actual runtime type checking # (which means we can't use validators) but we do want to ensure that `NotGiven` # values are not present # # type ignore required because we're adding explicit types to `**values` @classmethod def construct( # type: ignore cls, _fields_set: set[str] | None = None, **values: Unpack[FinalRequestOptionsInput], ) -> FinalRequestOptions: kwargs: dict[str, Any] = { # we unconditionally call `strip_not_given` on any value # as it will just ignore any non-mapping types key: strip_not_given(value) for key, value in values.items() } if PYDANTIC_V1: return cast(FinalRequestOptions, super().construct(_fields_set, **kwargs)) # pyright: ignore[reportDeprecated] return super().model_construct(_fields_set, **kwargs) if not TYPE_CHECKING: # type checkers incorrectly complain about this assignment model_construct = construct ================================================ FILE: src/openai/_module_client.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import TYPE_CHECKING from typing_extensions import override if TYPE_CHECKING: from .resources.files import Files from .resources.images import Images from .resources.models import Models from .resources.videos import Videos from .resources.batches import Batches from .resources.beta.beta import Beta from .resources.chat.chat import Chat from .resources.embeddings import Embeddings from .resources.audio.audio import Audio from .resources.completions import Completions from .resources.evals.evals import Evals from .resources.moderations import Moderations from .resources.skills.skills import Skills from .resources.uploads.uploads import Uploads from .resources.realtime.realtime import Realtime from .resources.webhooks.webhooks import Webhooks from .resources.responses.responses import Responses from .resources.containers.containers import Containers from .resources.fine_tuning.fine_tuning import FineTuning from .resources.conversations.conversations import Conversations from .resources.vector_stores.vector_stores import VectorStores from . import _load_client from ._utils import LazyProxy class ChatProxy(LazyProxy["Chat"]): @override def __load__(self) -> Chat: return _load_client().chat class BetaProxy(LazyProxy["Beta"]): @override def __load__(self) -> Beta: return _load_client().beta class FilesProxy(LazyProxy["Files"]): @override def __load__(self) -> Files: return _load_client().files class AudioProxy(LazyProxy["Audio"]): @override def __load__(self) -> Audio: return _load_client().audio class EvalsProxy(LazyProxy["Evals"]): @override def __load__(self) -> Evals: return _load_client().evals class ImagesProxy(LazyProxy["Images"]): @override def __load__(self) -> Images: return _load_client().images class ModelsProxy(LazyProxy["Models"]): @override def __load__(self) -> Models: return _load_client().models class SkillsProxy(LazyProxy["Skills"]): @override def __load__(self) -> Skills: return _load_client().skills class VideosProxy(LazyProxy["Videos"]): @override def __load__(self) -> Videos: return _load_client().videos class BatchesProxy(LazyProxy["Batches"]): @override def __load__(self) -> Batches: return _load_client().batches class UploadsProxy(LazyProxy["Uploads"]): @override def __load__(self) -> Uploads: return _load_client().uploads class WebhooksProxy(LazyProxy["Webhooks"]): @override def __load__(self) -> Webhooks: return _load_client().webhooks class RealtimeProxy(LazyProxy["Realtime"]): @override def __load__(self) -> Realtime: return _load_client().realtime class ResponsesProxy(LazyProxy["Responses"]): @override def __load__(self) -> Responses: return _load_client().responses class EmbeddingsProxy(LazyProxy["Embeddings"]): @override def __load__(self) -> Embeddings: return _load_client().embeddings class ContainersProxy(LazyProxy["Containers"]): @override def __load__(self) -> Containers: return _load_client().containers class CompletionsProxy(LazyProxy["Completions"]): @override def __load__(self) -> Completions: return _load_client().completions class ModerationsProxy(LazyProxy["Moderations"]): @override def __load__(self) -> Moderations: return _load_client().moderations class FineTuningProxy(LazyProxy["FineTuning"]): @override def __load__(self) -> FineTuning: return _load_client().fine_tuning class VectorStoresProxy(LazyProxy["VectorStores"]): @override def __load__(self) -> VectorStores: return _load_client().vector_stores class ConversationsProxy(LazyProxy["Conversations"]): @override def __load__(self) -> Conversations: return _load_client().conversations chat: Chat = ChatProxy().__as_proxied__() beta: Beta = BetaProxy().__as_proxied__() files: Files = FilesProxy().__as_proxied__() audio: Audio = AudioProxy().__as_proxied__() evals: Evals = EvalsProxy().__as_proxied__() images: Images = ImagesProxy().__as_proxied__() models: Models = ModelsProxy().__as_proxied__() skills: Skills = SkillsProxy().__as_proxied__() videos: Videos = VideosProxy().__as_proxied__() batches: Batches = BatchesProxy().__as_proxied__() uploads: Uploads = UploadsProxy().__as_proxied__() webhooks: Webhooks = WebhooksProxy().__as_proxied__() realtime: Realtime = RealtimeProxy().__as_proxied__() responses: Responses = ResponsesProxy().__as_proxied__() embeddings: Embeddings = EmbeddingsProxy().__as_proxied__() containers: Containers = ContainersProxy().__as_proxied__() completions: Completions = CompletionsProxy().__as_proxied__() moderations: Moderations = ModerationsProxy().__as_proxied__() fine_tuning: FineTuning = FineTuningProxy().__as_proxied__() vector_stores: VectorStores = VectorStoresProxy().__as_proxied__() conversations: Conversations = ConversationsProxy().__as_proxied__() ================================================ FILE: src/openai/_qs.py ================================================ from __future__ import annotations from typing import Any, List, Tuple, Union, Mapping, TypeVar from urllib.parse import parse_qs, urlencode from typing_extensions import Literal, get_args from ._types import NotGiven, not_given from ._utils import flatten _T = TypeVar("_T") ArrayFormat = Literal["comma", "repeat", "indices", "brackets"] NestedFormat = Literal["dots", "brackets"] PrimitiveData = Union[str, int, float, bool, None] # this should be Data = Union[PrimitiveData, "List[Data]", "Tuple[Data]", "Mapping[str, Data]"] # https://github.com/microsoft/pyright/issues/3555 Data = Union[PrimitiveData, List[Any], Tuple[Any], "Mapping[str, Any]"] Params = Mapping[str, Data] class Querystring: array_format: ArrayFormat nested_format: NestedFormat def __init__( self, *, array_format: ArrayFormat = "repeat", nested_format: NestedFormat = "brackets", ) -> None: self.array_format = array_format self.nested_format = nested_format def parse(self, query: str) -> Mapping[str, object]: # Note: custom format syntax is not supported yet return parse_qs(query) def stringify( self, params: Params, *, array_format: ArrayFormat | NotGiven = not_given, nested_format: NestedFormat | NotGiven = not_given, ) -> str: return urlencode( self.stringify_items( params, array_format=array_format, nested_format=nested_format, ) ) def stringify_items( self, params: Params, *, array_format: ArrayFormat | NotGiven = not_given, nested_format: NestedFormat | NotGiven = not_given, ) -> list[tuple[str, str]]: opts = Options( qs=self, array_format=array_format, nested_format=nested_format, ) return flatten([self._stringify_item(key, value, opts) for key, value in params.items()]) def _stringify_item( self, key: str, value: Data, opts: Options, ) -> list[tuple[str, str]]: if isinstance(value, Mapping): items: list[tuple[str, str]] = [] nested_format = opts.nested_format for subkey, subvalue in value.items(): items.extend( self._stringify_item( # TODO: error if unknown format f"{key}.{subkey}" if nested_format == "dots" else f"{key}[{subkey}]", subvalue, opts, ) ) return items if isinstance(value, (list, tuple)): array_format = opts.array_format if array_format == "comma": return [ ( key, ",".join(self._primitive_value_to_str(item) for item in value if item is not None), ), ] elif array_format == "repeat": items = [] for item in value: items.extend(self._stringify_item(key, item, opts)) return items elif array_format == "indices": raise NotImplementedError("The array indices format is not supported yet") elif array_format == "brackets": items = [] key = key + "[]" for item in value: items.extend(self._stringify_item(key, item, opts)) return items else: raise NotImplementedError( f"Unknown array_format value: {array_format}, choose from {', '.join(get_args(ArrayFormat))}" ) serialised = self._primitive_value_to_str(value) if not serialised: return [] return [(key, serialised)] def _primitive_value_to_str(self, value: PrimitiveData) -> str: # copied from httpx if value is True: return "true" elif value is False: return "false" elif value is None: return "" return str(value) _qs = Querystring() parse = _qs.parse stringify = _qs.stringify stringify_items = _qs.stringify_items class Options: array_format: ArrayFormat nested_format: NestedFormat def __init__( self, qs: Querystring = _qs, *, array_format: ArrayFormat | NotGiven = not_given, nested_format: NestedFormat | NotGiven = not_given, ) -> None: self.array_format = qs.array_format if isinstance(array_format, NotGiven) else array_format self.nested_format = qs.nested_format if isinstance(nested_format, NotGiven) else nested_format ================================================ FILE: src/openai/_resource.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import time from typing import TYPE_CHECKING import anyio if TYPE_CHECKING: from ._client import OpenAI, AsyncOpenAI class SyncAPIResource: _client: OpenAI def __init__(self, client: OpenAI) -> None: self._client = client self._get = client.get self._post = client.post self._patch = client.patch self._put = client.put self._delete = client.delete self._get_api_list = client.get_api_list def _sleep(self, seconds: float) -> None: time.sleep(seconds) class AsyncAPIResource: _client: AsyncOpenAI def __init__(self, client: AsyncOpenAI) -> None: self._client = client self._get = client.get self._post = client.post self._patch = client.patch self._put = client.put self._delete = client.delete self._get_api_list = client.get_api_list async def _sleep(self, seconds: float) -> None: await anyio.sleep(seconds) ================================================ FILE: src/openai/_response.py ================================================ from __future__ import annotations import os import inspect import logging import datetime import functools from types import TracebackType from typing import ( TYPE_CHECKING, Any, Union, Generic, TypeVar, Callable, Iterator, AsyncIterator, cast, overload, ) from typing_extensions import Awaitable, ParamSpec, override, get_origin import anyio import httpx import pydantic from ._types import NoneType from ._utils import is_given, extract_type_arg, is_annotated_type, is_type_alias_type, extract_type_var_from_base from ._models import BaseModel, is_basemodel, add_request_id from ._constants import RAW_RESPONSE_HEADER, OVERRIDE_CAST_TO_HEADER from ._streaming import Stream, AsyncStream, is_stream_class_type, extract_stream_chunk_type from ._exceptions import OpenAIError, APIResponseValidationError if TYPE_CHECKING: from ._models import FinalRequestOptions from ._base_client import BaseClient P = ParamSpec("P") R = TypeVar("R") _T = TypeVar("_T") _APIResponseT = TypeVar("_APIResponseT", bound="APIResponse[Any]") _AsyncAPIResponseT = TypeVar("_AsyncAPIResponseT", bound="AsyncAPIResponse[Any]") log: logging.Logger = logging.getLogger(__name__) class BaseAPIResponse(Generic[R]): _cast_to: type[R] _client: BaseClient[Any, Any] _parsed_by_type: dict[type[Any], Any] _is_sse_stream: bool _stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None _options: FinalRequestOptions http_response: httpx.Response retries_taken: int """The number of retries made. If no retries happened this will be `0`""" def __init__( self, *, raw: httpx.Response, cast_to: type[R], client: BaseClient[Any, Any], stream: bool, stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None, options: FinalRequestOptions, retries_taken: int = 0, ) -> None: self._cast_to = cast_to self._client = client self._parsed_by_type = {} self._is_sse_stream = stream self._stream_cls = stream_cls self._options = options self.http_response = raw self.retries_taken = retries_taken @property def headers(self) -> httpx.Headers: return self.http_response.headers @property def http_request(self) -> httpx.Request: """Returns the httpx Request instance associated with the current response.""" return self.http_response.request @property def status_code(self) -> int: return self.http_response.status_code @property def url(self) -> httpx.URL: """Returns the URL for which the request was made.""" return self.http_response.url @property def method(self) -> str: return self.http_request.method @property def http_version(self) -> str: return self.http_response.http_version @property def elapsed(self) -> datetime.timedelta: """The time taken for the complete request/response cycle to complete.""" return self.http_response.elapsed @property def is_closed(self) -> bool: """Whether or not the response body has been closed. If this is False then there is response data that has not been read yet. You must either fully consume the response body or call `.close()` before discarding the response to prevent resource leaks. """ return self.http_response.is_closed @override def __repr__(self) -> str: return ( f"<{self.__class__.__name__} [{self.status_code} {self.http_response.reason_phrase}] type={self._cast_to}>" ) def _parse(self, *, to: type[_T] | None = None) -> R | _T: cast_to = to if to is not None else self._cast_to # unwrap `TypeAlias('Name', T)` -> `T` if is_type_alias_type(cast_to): cast_to = cast_to.__value__ # type: ignore[unreachable] # unwrap `Annotated[T, ...]` -> `T` if cast_to and is_annotated_type(cast_to): cast_to = extract_type_arg(cast_to, 0) origin = get_origin(cast_to) or cast_to if self._is_sse_stream: if to: if not is_stream_class_type(to): raise TypeError(f"Expected custom parse type to be a subclass of {Stream} or {AsyncStream}") return cast( _T, to( cast_to=extract_stream_chunk_type( to, failure_message="Expected custom stream type to be passed with a type argument, e.g. Stream[ChunkType]", ), response=self.http_response, client=cast(Any, self._client), options=self._options, ), ) if self._stream_cls: return cast( R, self._stream_cls( cast_to=extract_stream_chunk_type(self._stream_cls), response=self.http_response, client=cast(Any, self._client), options=self._options, ), ) stream_cls = cast("type[Stream[Any]] | type[AsyncStream[Any]] | None", self._client._default_stream_cls) if stream_cls is None: raise MissingStreamClassError() return cast( R, stream_cls( cast_to=cast_to, response=self.http_response, client=cast(Any, self._client), options=self._options, ), ) if cast_to is NoneType: return cast(R, None) response = self.http_response if cast_to == str: return cast(R, response.text) if cast_to == bytes: return cast(R, response.content) if cast_to == int: return cast(R, int(response.text)) if cast_to == float: return cast(R, float(response.text)) if cast_to == bool: return cast(R, response.text.lower() == "true") # handle the legacy binary response case if inspect.isclass(cast_to) and cast_to.__name__ == "HttpxBinaryResponseContent": return cast(R, cast_to(response)) # type: ignore if origin == APIResponse: raise RuntimeError("Unexpected state - cast_to is `APIResponse`") if inspect.isclass(origin) and issubclass(origin, httpx.Response): # Because of the invariance of our ResponseT TypeVar, users can subclass httpx.Response # and pass that class to our request functions. We cannot change the variance to be either # covariant or contravariant as that makes our usage of ResponseT illegal. We could construct # the response class ourselves but that is something that should be supported directly in httpx # as it would be easy to incorrectly construct the Response object due to the multitude of arguments. if cast_to != httpx.Response: raise ValueError(f"Subclasses of httpx.Response cannot be passed to `cast_to`") return cast(R, response) if ( inspect.isclass( origin # pyright: ignore[reportUnknownArgumentType] ) and not issubclass(origin, BaseModel) and issubclass(origin, pydantic.BaseModel) ): raise TypeError("Pydantic models must subclass our base model type, e.g. `from openai import BaseModel`") if ( cast_to is not object and not origin is list and not origin is dict and not origin is Union and not issubclass(origin, BaseModel) ): raise RuntimeError( f"Unsupported type, expected {cast_to} to be a subclass of {BaseModel}, {dict}, {list}, {Union}, {NoneType}, {str} or {httpx.Response}." ) # split is required to handle cases where additional information is included # in the response, e.g. application/json; charset=utf-8 content_type, *_ = response.headers.get("content-type", "*").split(";") if not content_type.endswith("json"): if is_basemodel(cast_to): try: data = response.json() except Exception as exc: log.debug("Could not read JSON from response data due to %s - %s", type(exc), exc) else: return self._client._process_response_data( data=data, cast_to=cast_to, # type: ignore response=response, ) if self._client._strict_response_validation: raise APIResponseValidationError( response=response, message=f"Expected Content-Type response header to be `application/json` but received `{content_type}` instead.", body=response.text, ) # If the API responds with content that isn't JSON then we just return # the (decoded) text without performing any parsing so that you can still # handle the response however you need to. return response.text # type: ignore data = response.json() return self._client._process_response_data( data=data, cast_to=cast_to, # type: ignore response=response, ) class APIResponse(BaseAPIResponse[R]): @property def request_id(self) -> str | None: return self.http_response.headers.get("x-request-id") # type: ignore[no-any-return] @overload def parse(self, *, to: type[_T]) -> _T: ... @overload def parse(self) -> R: ... def parse(self, *, to: type[_T] | None = None) -> R | _T: """Returns the rich python representation of this response's data. For lower-level control, see `.read()`, `.json()`, `.iter_bytes()`. You can customise the type that the response is parsed into through the `to` argument, e.g. ```py from openai import BaseModel class MyModel(BaseModel): foo: str obj = response.parse(to=MyModel) print(obj.foo) ``` We support parsing: - `BaseModel` - `dict` - `list` - `Union` - `str` - `int` - `float` - `httpx.Response` """ cache_key = to if to is not None else self._cast_to cached = self._parsed_by_type.get(cache_key) if cached is not None: return cached # type: ignore[no-any-return] if not self._is_sse_stream: self.read() parsed = self._parse(to=to) if is_given(self._options.post_parser): parsed = self._options.post_parser(parsed) if isinstance(parsed, BaseModel): add_request_id(parsed, self.request_id) self._parsed_by_type[cache_key] = parsed return cast(R, parsed) def read(self) -> bytes: """Read and return the binary response content.""" try: return self.http_response.read() except httpx.StreamConsumed as exc: # The default error raised by httpx isn't very # helpful in our case so we re-raise it with # a different error message. raise StreamAlreadyConsumed() from exc def text(self) -> str: """Read and decode the response content into a string.""" self.read() return self.http_response.text def json(self) -> object: """Read and decode the JSON response content.""" self.read() return self.http_response.json() def close(self) -> None: """Close the response and release the connection. Automatically called if the response body is read to completion. """ self.http_response.close() def iter_bytes(self, chunk_size: int | None = None) -> Iterator[bytes]: """ A byte-iterator over the decoded response content. This automatically handles gzip, deflate and brotli encoded responses. """ for chunk in self.http_response.iter_bytes(chunk_size): yield chunk def iter_text(self, chunk_size: int | None = None) -> Iterator[str]: """A str-iterator over the decoded response content that handles both gzip, deflate, etc but also detects the content's string encoding. """ for chunk in self.http_response.iter_text(chunk_size): yield chunk def iter_lines(self) -> Iterator[str]: """Like `iter_text()` but will only yield chunks for each line""" for chunk in self.http_response.iter_lines(): yield chunk class AsyncAPIResponse(BaseAPIResponse[R]): @property def request_id(self) -> str | None: return self.http_response.headers.get("x-request-id") # type: ignore[no-any-return] @overload async def parse(self, *, to: type[_T]) -> _T: ... @overload async def parse(self) -> R: ... async def parse(self, *, to: type[_T] | None = None) -> R | _T: """Returns the rich python representation of this response's data. For lower-level control, see `.read()`, `.json()`, `.iter_bytes()`. You can customise the type that the response is parsed into through the `to` argument, e.g. ```py from openai import BaseModel class MyModel(BaseModel): foo: str obj = response.parse(to=MyModel) print(obj.foo) ``` We support parsing: - `BaseModel` - `dict` - `list` - `Union` - `str` - `httpx.Response` """ cache_key = to if to is not None else self._cast_to cached = self._parsed_by_type.get(cache_key) if cached is not None: return cached # type: ignore[no-any-return] if not self._is_sse_stream: await self.read() parsed = self._parse(to=to) if is_given(self._options.post_parser): parsed = self._options.post_parser(parsed) if isinstance(parsed, BaseModel): add_request_id(parsed, self.request_id) self._parsed_by_type[cache_key] = parsed return cast(R, parsed) async def read(self) -> bytes: """Read and return the binary response content.""" try: return await self.http_response.aread() except httpx.StreamConsumed as exc: # the default error raised by httpx isn't very # helpful in our case so we re-raise it with # a different error message raise StreamAlreadyConsumed() from exc async def text(self) -> str: """Read and decode the response content into a string.""" await self.read() return self.http_response.text async def json(self) -> object: """Read and decode the JSON response content.""" await self.read() return self.http_response.json() async def close(self) -> None: """Close the response and release the connection. Automatically called if the response body is read to completion. """ await self.http_response.aclose() async def iter_bytes(self, chunk_size: int | None = None) -> AsyncIterator[bytes]: """ A byte-iterator over the decoded response content. This automatically handles gzip, deflate and brotli encoded responses. """ async for chunk in self.http_response.aiter_bytes(chunk_size): yield chunk async def iter_text(self, chunk_size: int | None = None) -> AsyncIterator[str]: """A str-iterator over the decoded response content that handles both gzip, deflate, etc but also detects the content's string encoding. """ async for chunk in self.http_response.aiter_text(chunk_size): yield chunk async def iter_lines(self) -> AsyncIterator[str]: """Like `iter_text()` but will only yield chunks for each line""" async for chunk in self.http_response.aiter_lines(): yield chunk class BinaryAPIResponse(APIResponse[bytes]): """Subclass of APIResponse providing helpers for dealing with binary data. Note: If you want to stream the response data instead of eagerly reading it all at once then you should use `.with_streaming_response` when making the API request, e.g. `.with_streaming_response.get_binary_response()` """ def write_to_file( self, file: str | os.PathLike[str], ) -> None: """Write the output to the given file. Accepts a filename or any path-like object, e.g. pathlib.Path Note: if you want to stream the data to the file instead of writing all at once then you should use `.with_streaming_response` when making the API request, e.g. `.with_streaming_response.get_binary_response()` """ with open(file, mode="wb") as f: for data in self.iter_bytes(): f.write(data) class AsyncBinaryAPIResponse(AsyncAPIResponse[bytes]): """Subclass of APIResponse providing helpers for dealing with binary data. Note: If you want to stream the response data instead of eagerly reading it all at once then you should use `.with_streaming_response` when making the API request, e.g. `.with_streaming_response.get_binary_response()` """ async def write_to_file( self, file: str | os.PathLike[str], ) -> None: """Write the output to the given file. Accepts a filename or any path-like object, e.g. pathlib.Path Note: if you want to stream the data to the file instead of writing all at once then you should use `.with_streaming_response` when making the API request, e.g. `.with_streaming_response.get_binary_response()` """ path = anyio.Path(file) async with await path.open(mode="wb") as f: async for data in self.iter_bytes(): await f.write(data) class StreamedBinaryAPIResponse(APIResponse[bytes]): def stream_to_file( self, file: str | os.PathLike[str], *, chunk_size: int | None = None, ) -> None: """Streams the output to the given file. Accepts a filename or any path-like object, e.g. pathlib.Path """ with open(file, mode="wb") as f: for data in self.iter_bytes(chunk_size): f.write(data) class AsyncStreamedBinaryAPIResponse(AsyncAPIResponse[bytes]): async def stream_to_file( self, file: str | os.PathLike[str], *, chunk_size: int | None = None, ) -> None: """Streams the output to the given file. Accepts a filename or any path-like object, e.g. pathlib.Path """ path = anyio.Path(file) async with await path.open(mode="wb") as f: async for data in self.iter_bytes(chunk_size): await f.write(data) class MissingStreamClassError(TypeError): def __init__(self) -> None: super().__init__( "The `stream` argument was set to `True` but the `stream_cls` argument was not given. See `openai._streaming` for reference", ) class StreamAlreadyConsumed(OpenAIError): """ Attempted to read or stream content, but the content has already been streamed. This can happen if you use a method like `.iter_lines()` and then attempt to read th entire response body afterwards, e.g. ```py response = await client.post(...) async for line in response.iter_lines(): ... # do something with `line` content = await response.read() # ^ error ``` If you want this behaviour you'll need to either manually accumulate the response content or call `await response.read()` before iterating over the stream. """ def __init__(self) -> None: message = ( "Attempted to read or stream some content, but the content has " "already been streamed. " "This could be due to attempting to stream the response " "content more than once." "\n\n" "You can fix this by manually accumulating the response content while streaming " "or by calling `.read()` before starting to stream." ) super().__init__(message) class ResponseContextManager(Generic[_APIResponseT]): """Context manager for ensuring that a request is not made until it is entered and that the response will always be closed when the context manager exits """ def __init__(self, request_func: Callable[[], _APIResponseT]) -> None: self._request_func = request_func self.__response: _APIResponseT | None = None def __enter__(self) -> _APIResponseT: self.__response = self._request_func() return self.__response def __exit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None, ) -> None: if self.__response is not None: self.__response.close() class AsyncResponseContextManager(Generic[_AsyncAPIResponseT]): """Context manager for ensuring that a request is not made until it is entered and that the response will always be closed when the context manager exits """ def __init__(self, api_request: Awaitable[_AsyncAPIResponseT]) -> None: self._api_request = api_request self.__response: _AsyncAPIResponseT | None = None async def __aenter__(self) -> _AsyncAPIResponseT: self.__response = await self._api_request return self.__response async def __aexit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None, ) -> None: if self.__response is not None: await self.__response.close() def to_streamed_response_wrapper(func: Callable[P, R]) -> Callable[P, ResponseContextManager[APIResponse[R]]]: """Higher order function that takes one of our bound API methods and wraps it to support streaming and returning the raw `APIResponse` object directly. """ @functools.wraps(func) def wrapped(*args: P.args, **kwargs: P.kwargs) -> ResponseContextManager[APIResponse[R]]: extra_headers: dict[str, str] = {**(cast(Any, kwargs.get("extra_headers")) or {})} extra_headers[RAW_RESPONSE_HEADER] = "stream" kwargs["extra_headers"] = extra_headers make_request = functools.partial(func, *args, **kwargs) return ResponseContextManager(cast(Callable[[], APIResponse[R]], make_request)) return wrapped def async_to_streamed_response_wrapper( func: Callable[P, Awaitable[R]], ) -> Callable[P, AsyncResponseContextManager[AsyncAPIResponse[R]]]: """Higher order function that takes one of our bound API methods and wraps it to support streaming and returning the raw `APIResponse` object directly. """ @functools.wraps(func) def wrapped(*args: P.args, **kwargs: P.kwargs) -> AsyncResponseContextManager[AsyncAPIResponse[R]]: extra_headers: dict[str, str] = {**(cast(Any, kwargs.get("extra_headers")) or {})} extra_headers[RAW_RESPONSE_HEADER] = "stream" kwargs["extra_headers"] = extra_headers make_request = func(*args, **kwargs) return AsyncResponseContextManager(cast(Awaitable[AsyncAPIResponse[R]], make_request)) return wrapped def to_custom_streamed_response_wrapper( func: Callable[P, object], response_cls: type[_APIResponseT], ) -> Callable[P, ResponseContextManager[_APIResponseT]]: """Higher order function that takes one of our bound API methods and an `APIResponse` class and wraps the method to support streaming and returning the given response class directly. Note: the given `response_cls` *must* be concrete, e.g. `class BinaryAPIResponse(APIResponse[bytes])` """ @functools.wraps(func) def wrapped(*args: P.args, **kwargs: P.kwargs) -> ResponseContextManager[_APIResponseT]: extra_headers: dict[str, Any] = {**(cast(Any, kwargs.get("extra_headers")) or {})} extra_headers[RAW_RESPONSE_HEADER] = "stream" extra_headers[OVERRIDE_CAST_TO_HEADER] = response_cls kwargs["extra_headers"] = extra_headers make_request = functools.partial(func, *args, **kwargs) return ResponseContextManager(cast(Callable[[], _APIResponseT], make_request)) return wrapped def async_to_custom_streamed_response_wrapper( func: Callable[P, Awaitable[object]], response_cls: type[_AsyncAPIResponseT], ) -> Callable[P, AsyncResponseContextManager[_AsyncAPIResponseT]]: """Higher order function that takes one of our bound API methods and an `APIResponse` class and wraps the method to support streaming and returning the given response class directly. Note: the given `response_cls` *must* be concrete, e.g. `class BinaryAPIResponse(APIResponse[bytes])` """ @functools.wraps(func) def wrapped(*args: P.args, **kwargs: P.kwargs) -> AsyncResponseContextManager[_AsyncAPIResponseT]: extra_headers: dict[str, Any] = {**(cast(Any, kwargs.get("extra_headers")) or {})} extra_headers[RAW_RESPONSE_HEADER] = "stream" extra_headers[OVERRIDE_CAST_TO_HEADER] = response_cls kwargs["extra_headers"] = extra_headers make_request = func(*args, **kwargs) return AsyncResponseContextManager(cast(Awaitable[_AsyncAPIResponseT], make_request)) return wrapped def to_raw_response_wrapper(func: Callable[P, R]) -> Callable[P, APIResponse[R]]: """Higher order function that takes one of our bound API methods and wraps it to support returning the raw `APIResponse` object directly. """ @functools.wraps(func) def wrapped(*args: P.args, **kwargs: P.kwargs) -> APIResponse[R]: extra_headers: dict[str, str] = {**(cast(Any, kwargs.get("extra_headers")) or {})} extra_headers[RAW_RESPONSE_HEADER] = "raw" kwargs["extra_headers"] = extra_headers return cast(APIResponse[R], func(*args, **kwargs)) return wrapped def async_to_raw_response_wrapper(func: Callable[P, Awaitable[R]]) -> Callable[P, Awaitable[AsyncAPIResponse[R]]]: """Higher order function that takes one of our bound API methods and wraps it to support returning the raw `APIResponse` object directly. """ @functools.wraps(func) async def wrapped(*args: P.args, **kwargs: P.kwargs) -> AsyncAPIResponse[R]: extra_headers: dict[str, str] = {**(cast(Any, kwargs.get("extra_headers")) or {})} extra_headers[RAW_RESPONSE_HEADER] = "raw" kwargs["extra_headers"] = extra_headers return cast(AsyncAPIResponse[R], await func(*args, **kwargs)) return wrapped def to_custom_raw_response_wrapper( func: Callable[P, object], response_cls: type[_APIResponseT], ) -> Callable[P, _APIResponseT]: """Higher order function that takes one of our bound API methods and an `APIResponse` class and wraps the method to support returning the given response class directly. Note: the given `response_cls` *must* be concrete, e.g. `class BinaryAPIResponse(APIResponse[bytes])` """ @functools.wraps(func) def wrapped(*args: P.args, **kwargs: P.kwargs) -> _APIResponseT: extra_headers: dict[str, Any] = {**(cast(Any, kwargs.get("extra_headers")) or {})} extra_headers[RAW_RESPONSE_HEADER] = "raw" extra_headers[OVERRIDE_CAST_TO_HEADER] = response_cls kwargs["extra_headers"] = extra_headers return cast(_APIResponseT, func(*args, **kwargs)) return wrapped def async_to_custom_raw_response_wrapper( func: Callable[P, Awaitable[object]], response_cls: type[_AsyncAPIResponseT], ) -> Callable[P, Awaitable[_AsyncAPIResponseT]]: """Higher order function that takes one of our bound API methods and an `APIResponse` class and wraps the method to support returning the given response class directly. Note: the given `response_cls` *must* be concrete, e.g. `class BinaryAPIResponse(APIResponse[bytes])` """ @functools.wraps(func) def wrapped(*args: P.args, **kwargs: P.kwargs) -> Awaitable[_AsyncAPIResponseT]: extra_headers: dict[str, Any] = {**(cast(Any, kwargs.get("extra_headers")) or {})} extra_headers[RAW_RESPONSE_HEADER] = "raw" extra_headers[OVERRIDE_CAST_TO_HEADER] = response_cls kwargs["extra_headers"] = extra_headers return cast(Awaitable[_AsyncAPIResponseT], func(*args, **kwargs)) return wrapped def extract_response_type(typ: type[BaseAPIResponse[Any]]) -> type: """Given a type like `APIResponse[T]`, returns the generic type variable `T`. This also handles the case where a concrete subclass is given, e.g. ```py class MyResponse(APIResponse[bytes]): ... extract_response_type(MyResponse) -> bytes ``` """ return extract_type_var_from_base( typ, generic_bases=cast("tuple[type, ...]", (BaseAPIResponse, APIResponse, AsyncAPIResponse)), index=0, ) ================================================ FILE: src/openai/_streaming.py ================================================ # Note: initially copied from https://github.com/florimondmanca/httpx-sse/blob/master/src/httpx_sse/_decoders.py from __future__ import annotations import json import inspect from types import TracebackType from typing import TYPE_CHECKING, Any, Generic, TypeVar, Iterator, Optional, AsyncIterator, cast from typing_extensions import Self, Protocol, TypeGuard, override, get_origin, runtime_checkable import httpx from ._utils import is_mapping, extract_type_var_from_base from ._exceptions import APIError if TYPE_CHECKING: from ._client import OpenAI, AsyncOpenAI from ._models import FinalRequestOptions _T = TypeVar("_T") class Stream(Generic[_T]): """Provides the core interface to iterate over a synchronous stream response.""" response: httpx.Response _options: Optional[FinalRequestOptions] = None _decoder: SSEBytesDecoder def __init__( self, *, cast_to: type[_T], response: httpx.Response, client: OpenAI, options: Optional[FinalRequestOptions] = None, ) -> None: self.response = response self._cast_to = cast_to self._client = client self._options = options self._decoder = client._make_sse_decoder() self._iterator = self.__stream__() def __next__(self) -> _T: return self._iterator.__next__() def __iter__(self) -> Iterator[_T]: for item in self._iterator: yield item def _iter_events(self) -> Iterator[ServerSentEvent]: yield from self._decoder.iter_bytes(self.response.iter_bytes()) def __stream__(self) -> Iterator[_T]: cast_to = cast(Any, self._cast_to) response = self.response process_data = self._client._process_response_data iterator = self._iter_events() try: for sse in iterator: if sse.data.startswith("[DONE]"): break # we have to special case the Assistants `thread.` events since we won't have an "event" key in the data if sse.event and sse.event.startswith("thread."): data = sse.json() if sse.event == "error" and is_mapping(data) and data.get("error"): message = None error = data.get("error") if is_mapping(error): message = error.get("message") if not message or not isinstance(message, str): message = "An error occurred during streaming" raise APIError( message=message, request=self.response.request, body=data["error"], ) yield process_data(data={"data": data, "event": sse.event}, cast_to=cast_to, response=response) else: data = sse.json() if is_mapping(data) and data.get("error"): message = None error = data.get("error") if is_mapping(error): message = error.get("message") if not message or not isinstance(message, str): message = "An error occurred during streaming" raise APIError( message=message, request=self.response.request, body=data["error"], ) yield process_data( data={"data": data, "event": sse.event} if self._options is not None and self._options.synthesize_event_and_data else data, cast_to=cast_to, response=response, ) finally: # Ensure the response is closed even if the consumer doesn't read all data response.close() def __enter__(self) -> Self: return self def __exit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None, ) -> None: self.close() def close(self) -> None: """ Close the response and release the connection. Automatically called if the response body is read to completion. """ self.response.close() class AsyncStream(Generic[_T]): """Provides the core interface to iterate over an asynchronous stream response.""" response: httpx.Response _options: Optional[FinalRequestOptions] = None _decoder: SSEDecoder | SSEBytesDecoder def __init__( self, *, cast_to: type[_T], response: httpx.Response, client: AsyncOpenAI, options: Optional[FinalRequestOptions] = None, ) -> None: self.response = response self._cast_to = cast_to self._client = client self._options = options self._decoder = client._make_sse_decoder() self._iterator = self.__stream__() async def __anext__(self) -> _T: return await self._iterator.__anext__() async def __aiter__(self) -> AsyncIterator[_T]: async for item in self._iterator: yield item async def _iter_events(self) -> AsyncIterator[ServerSentEvent]: async for sse in self._decoder.aiter_bytes(self.response.aiter_bytes()): yield sse async def __stream__(self) -> AsyncIterator[_T]: cast_to = cast(Any, self._cast_to) response = self.response process_data = self._client._process_response_data iterator = self._iter_events() try: async for sse in iterator: if sse.data.startswith("[DONE]"): break # we have to special case the Assistants `thread.` events since we won't have an "event" key in the data if sse.event and sse.event.startswith("thread."): data = sse.json() if sse.event == "error" and is_mapping(data) and data.get("error"): message = None error = data.get("error") if is_mapping(error): message = error.get("message") if not message or not isinstance(message, str): message = "An error occurred during streaming" raise APIError( message=message, request=self.response.request, body=data["error"], ) yield process_data(data={"data": data, "event": sse.event}, cast_to=cast_to, response=response) else: data = sse.json() if is_mapping(data) and data.get("error"): message = None error = data.get("error") if is_mapping(error): message = error.get("message") if not message or not isinstance(message, str): message = "An error occurred during streaming" raise APIError( message=message, request=self.response.request, body=data["error"], ) yield process_data( data={"data": data, "event": sse.event} if self._options is not None and self._options.synthesize_event_and_data else data, cast_to=cast_to, response=response, ) finally: # Ensure the response is closed even if the consumer doesn't read all data await response.aclose() async def __aenter__(self) -> Self: return self async def __aexit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None, ) -> None: await self.close() async def close(self) -> None: """ Close the response and release the connection. Automatically called if the response body is read to completion. """ await self.response.aclose() class ServerSentEvent: def __init__( self, *, event: str | None = None, data: str | None = None, id: str | None = None, retry: int | None = None, ) -> None: if data is None: data = "" self._id = id self._data = data self._event = event or None self._retry = retry @property def event(self) -> str | None: return self._event @property def id(self) -> str | None: return self._id @property def retry(self) -> int | None: return self._retry @property def data(self) -> str: return self._data def json(self) -> Any: return json.loads(self.data) @override def __repr__(self) -> str: return f"ServerSentEvent(event={self.event}, data={self.data}, id={self.id}, retry={self.retry})" class SSEDecoder: _data: list[str] _event: str | None _retry: int | None _last_event_id: str | None def __init__(self) -> None: self._event = None self._data = [] self._last_event_id = None self._retry = None def iter_bytes(self, iterator: Iterator[bytes]) -> Iterator[ServerSentEvent]: """Given an iterator that yields raw binary data, iterate over it & yield every event encountered""" for chunk in self._iter_chunks(iterator): # Split before decoding so splitlines() only uses \r and \n for raw_line in chunk.splitlines(): line = raw_line.decode("utf-8") sse = self.decode(line) if sse: yield sse def _iter_chunks(self, iterator: Iterator[bytes]) -> Iterator[bytes]: """Given an iterator that yields raw binary data, iterate over it and yield individual SSE chunks""" data = b"" for chunk in iterator: for line in chunk.splitlines(keepends=True): data += line if data.endswith((b"\r\r", b"\n\n", b"\r\n\r\n")): yield data data = b"" if data: yield data async def aiter_bytes(self, iterator: AsyncIterator[bytes]) -> AsyncIterator[ServerSentEvent]: """Given an iterator that yields raw binary data, iterate over it & yield every event encountered""" async for chunk in self._aiter_chunks(iterator): # Split before decoding so splitlines() only uses \r and \n for raw_line in chunk.splitlines(): line = raw_line.decode("utf-8") sse = self.decode(line) if sse: yield sse async def _aiter_chunks(self, iterator: AsyncIterator[bytes]) -> AsyncIterator[bytes]: """Given an iterator that yields raw binary data, iterate over it and yield individual SSE chunks""" data = b"" async for chunk in iterator: for line in chunk.splitlines(keepends=True): data += line if data.endswith((b"\r\r", b"\n\n", b"\r\n\r\n")): yield data data = b"" if data: yield data def decode(self, line: str) -> ServerSentEvent | None: # See: https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation # noqa: E501 if not line: if not self._event and not self._data and not self._last_event_id and self._retry is None: return None sse = ServerSentEvent( event=self._event, data="\n".join(self._data), id=self._last_event_id, retry=self._retry, ) # NOTE: as per the SSE spec, do not reset last_event_id. self._event = None self._data = [] self._retry = None return sse if line.startswith(":"): return None fieldname, _, value = line.partition(":") if value.startswith(" "): value = value[1:] if fieldname == "event": self._event = value elif fieldname == "data": self._data.append(value) elif fieldname == "id": if "\0" in value: pass else: self._last_event_id = value elif fieldname == "retry": try: self._retry = int(value) except (TypeError, ValueError): pass else: pass # Field is ignored. return None @runtime_checkable class SSEBytesDecoder(Protocol): def iter_bytes(self, iterator: Iterator[bytes]) -> Iterator[ServerSentEvent]: """Given an iterator that yields raw binary data, iterate over it & yield every event encountered""" ... def aiter_bytes(self, iterator: AsyncIterator[bytes]) -> AsyncIterator[ServerSentEvent]: """Given an async iterator that yields raw binary data, iterate over it & yield every event encountered""" ... def is_stream_class_type(typ: type) -> TypeGuard[type[Stream[object]] | type[AsyncStream[object]]]: """TypeGuard for determining whether or not the given type is a subclass of `Stream` / `AsyncStream`""" origin = get_origin(typ) or typ return inspect.isclass(origin) and issubclass(origin, (Stream, AsyncStream)) def extract_stream_chunk_type( stream_cls: type, *, failure_message: str | None = None, ) -> type: """Given a type like `Stream[T]`, returns the generic type variable `T`. This also handles the case where a concrete subclass is given, e.g. ```py class MyStream(Stream[bytes]): ... extract_stream_chunk_type(MyStream) -> bytes ``` """ from ._base_client import Stream, AsyncStream return extract_type_var_from_base( stream_cls, index=0, generic_bases=cast("tuple[type, ...]", (Stream, AsyncStream)), failure_message=failure_message, ) ================================================ FILE: src/openai/_types.py ================================================ from __future__ import annotations from os import PathLike from typing import ( IO, TYPE_CHECKING, Any, Dict, List, Type, Tuple, Union, Mapping, TypeVar, Callable, Iterable, Iterator, Optional, Sequence, AsyncIterable, ) from typing_extensions import ( Set, Literal, Protocol, TypeAlias, TypedDict, SupportsIndex, overload, override, runtime_checkable, ) import httpx import pydantic from httpx import URL, Proxy, Timeout, Response, BaseTransport, AsyncBaseTransport if TYPE_CHECKING: from ._models import BaseModel from ._response import APIResponse, AsyncAPIResponse from ._legacy_response import HttpxBinaryResponseContent Transport = BaseTransport AsyncTransport = AsyncBaseTransport Query = Mapping[str, object] Body = object AnyMapping = Mapping[str, object] ModelT = TypeVar("ModelT", bound=pydantic.BaseModel) _T = TypeVar("_T") # Approximates httpx internal ProxiesTypes and RequestFiles types # while adding support for `PathLike` instances ProxiesDict = Dict["str | URL", Union[None, str, URL, Proxy]] ProxiesTypes = Union[str, Proxy, ProxiesDict] if TYPE_CHECKING: Base64FileInput = Union[IO[bytes], PathLike[str]] FileContent = Union[IO[bytes], bytes, PathLike[str]] else: Base64FileInput = Union[IO[bytes], PathLike] FileContent = Union[IO[bytes], bytes, PathLike] # PathLike is not subscriptable in Python 3.8. # Used for sending raw binary data / streaming data in request bodies # e.g. for file uploads without multipart encoding BinaryTypes = Union[bytes, bytearray, IO[bytes], Iterable[bytes]] AsyncBinaryTypes = Union[bytes, bytearray, IO[bytes], AsyncIterable[bytes]] FileTypes = Union[ # file (or bytes) FileContent, # (filename, file (or bytes)) Tuple[Optional[str], FileContent], # (filename, file (or bytes), content_type) Tuple[Optional[str], FileContent, Optional[str]], # (filename, file (or bytes), content_type, headers) Tuple[Optional[str], FileContent, Optional[str], Mapping[str, str]], ] RequestFiles = Union[Mapping[str, FileTypes], Sequence[Tuple[str, FileTypes]]] # duplicate of the above but without our custom file support HttpxFileContent = Union[IO[bytes], bytes] HttpxFileTypes = Union[ # file (or bytes) HttpxFileContent, # (filename, file (or bytes)) Tuple[Optional[str], HttpxFileContent], # (filename, file (or bytes), content_type) Tuple[Optional[str], HttpxFileContent, Optional[str]], # (filename, file (or bytes), content_type, headers) Tuple[Optional[str], HttpxFileContent, Optional[str], Mapping[str, str]], ] HttpxRequestFiles = Union[Mapping[str, HttpxFileTypes], Sequence[Tuple[str, HttpxFileTypes]]] # Workaround to support (cast_to: Type[ResponseT]) -> ResponseT # where ResponseT includes `None`. In order to support directly # passing `None`, overloads would have to be defined for every # method that uses `ResponseT` which would lead to an unacceptable # amount of code duplication and make it unreadable. See _base_client.py # for example usage. # # This unfortunately means that you will either have # to import this type and pass it explicitly: # # from openai import NoneType # client.get('/foo', cast_to=NoneType) # # or build it yourself: # # client.get('/foo', cast_to=type(None)) if TYPE_CHECKING: NoneType: Type[None] else: NoneType = type(None) class RequestOptions(TypedDict, total=False): headers: Headers max_retries: int timeout: float | Timeout | None params: Query extra_json: AnyMapping idempotency_key: str follow_redirects: bool synthesize_event_and_data: bool # Sentinel class used until PEP 0661 is accepted class NotGiven: """ For parameters with a meaningful None value, we need to distinguish between the user explicitly passing None, and the user not passing the parameter at all. User code shouldn't need to use not_given directly. For example: ```py def create(timeout: Timeout | None | NotGiven = not_given): ... create(timeout=1) # 1s timeout create(timeout=None) # No timeout create() # Default timeout behavior ``` """ def __bool__(self) -> Literal[False]: return False @override def __repr__(self) -> str: return "NOT_GIVEN" not_given = NotGiven() # for backwards compatibility: NOT_GIVEN = NotGiven() class Omit: """ To explicitly omit something from being sent in a request, use `omit`. ```py # as the default `Content-Type` header is `application/json` that will be sent client.post("/upload/files", files={"file": b"my raw file content"}) # you can't explicitly override the header as it has to be dynamically generated # to look something like: 'multipart/form-data; boundary=0d8382fcf5f8c3be01ca2e11002d2983' client.post(..., headers={"Content-Type": "multipart/form-data"}) # instead you can remove the default `application/json` header by passing omit client.post(..., headers={"Content-Type": omit}) ``` """ def __bool__(self) -> Literal[False]: return False omit = Omit() Omittable = Union[_T, Omit] @runtime_checkable class ModelBuilderProtocol(Protocol): @classmethod def build( cls: type[_T], *, response: Response, data: object, ) -> _T: ... Headers = Mapping[str, Union[str, Omit]] class HeadersLikeProtocol(Protocol): def get(self, __key: str) -> str | None: ... HeadersLike = Union[Headers, HeadersLikeProtocol] ResponseT = TypeVar( "ResponseT", bound=Union[ object, str, None, "BaseModel", List[Any], Dict[str, Any], Response, ModelBuilderProtocol, "APIResponse[Any]", "AsyncAPIResponse[Any]", "HttpxBinaryResponseContent", ], ) StrBytesIntFloat = Union[str, bytes, int, float] # Note: copied from Pydantic # https://github.com/pydantic/pydantic/blob/6f31f8f68ef011f84357330186f603ff295312fd/pydantic/main.py#L79 IncEx: TypeAlias = Union[Set[int], Set[str], Mapping[int, Union["IncEx", bool]], Mapping[str, Union["IncEx", bool]]] PostParser = Callable[[Any], Any] @runtime_checkable class InheritsGeneric(Protocol): """Represents a type that has inherited from `Generic` The `__orig_bases__` property can be used to determine the resolved type variable for a given base class. """ __orig_bases__: tuple[_GenericAlias] class _GenericAlias(Protocol): __origin__: type[object] class HttpxSendArgs(TypedDict, total=False): auth: httpx.Auth follow_redirects: bool _T_co = TypeVar("_T_co", covariant=True) if TYPE_CHECKING: # This works because str.__contains__ does not accept object (either in typeshed or at runtime) # https://github.com/hauntsaninja/useful_types/blob/5e9710f3875107d068e7679fd7fec9cfab0eff3b/useful_types/__init__.py#L285 # # Note: index() and count() methods are intentionally omitted to allow pyright to properly # infer TypedDict types when dict literals are used in lists assigned to SequenceNotStr. class SequenceNotStr(Protocol[_T_co]): @overload def __getitem__(self, index: SupportsIndex, /) -> _T_co: ... @overload def __getitem__(self, index: slice, /) -> Sequence[_T_co]: ... def __contains__(self, value: object, /) -> bool: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[_T_co]: ... def __reversed__(self) -> Iterator[_T_co]: ... else: # just point this to a normal `Sequence` at runtime to avoid having to special case # deserializing our custom sequence type SequenceNotStr = Sequence ================================================ FILE: src/openai/_utils/__init__.py ================================================ from ._logs import SensitiveHeadersFilter as SensitiveHeadersFilter from ._sync import asyncify as asyncify from ._proxy import LazyProxy as LazyProxy from ._utils import ( flatten as flatten, is_dict as is_dict, is_list as is_list, is_given as is_given, is_tuple as is_tuple, json_safe as json_safe, lru_cache as lru_cache, is_mapping as is_mapping, is_tuple_t as is_tuple_t, is_iterable as is_iterable, is_sequence as is_sequence, coerce_float as coerce_float, is_mapping_t as is_mapping_t, removeprefix as removeprefix, removesuffix as removesuffix, extract_files as extract_files, is_sequence_t as is_sequence_t, required_args as required_args, coerce_boolean as coerce_boolean, coerce_integer as coerce_integer, file_from_path as file_from_path, is_azure_client as is_azure_client, strip_not_given as strip_not_given, deepcopy_minimal as deepcopy_minimal, get_async_library as get_async_library, maybe_coerce_float as maybe_coerce_float, get_required_header as get_required_header, maybe_coerce_boolean as maybe_coerce_boolean, maybe_coerce_integer as maybe_coerce_integer, is_async_azure_client as is_async_azure_client, ) from ._compat import ( get_args as get_args, is_union as is_union, get_origin as get_origin, is_typeddict as is_typeddict, is_literal_type as is_literal_type, ) from ._typing import ( is_list_type as is_list_type, is_union_type as is_union_type, extract_type_arg as extract_type_arg, is_iterable_type as is_iterable_type, is_required_type as is_required_type, is_sequence_type as is_sequence_type, is_annotated_type as is_annotated_type, is_type_alias_type as is_type_alias_type, strip_annotated_type as strip_annotated_type, extract_type_var_from_base as extract_type_var_from_base, ) from ._streams import consume_sync_iterator as consume_sync_iterator, consume_async_iterator as consume_async_iterator from ._transform import ( PropertyInfo as PropertyInfo, transform as transform, async_transform as async_transform, maybe_transform as maybe_transform, async_maybe_transform as async_maybe_transform, ) from ._reflection import ( function_has_argument as function_has_argument, assert_signatures_in_sync as assert_signatures_in_sync, ) from ._datetime_parse import parse_date as parse_date, parse_datetime as parse_datetime ================================================ FILE: src/openai/_utils/_compat.py ================================================ from __future__ import annotations import sys import typing_extensions from typing import Any, Type, Union, Literal, Optional from datetime import date, datetime from typing_extensions import get_args as _get_args, get_origin as _get_origin from .._types import StrBytesIntFloat from ._datetime_parse import parse_date as _parse_date, parse_datetime as _parse_datetime _LITERAL_TYPES = {Literal, typing_extensions.Literal} def get_args(tp: type[Any]) -> tuple[Any, ...]: return _get_args(tp) def get_origin(tp: type[Any]) -> type[Any] | None: return _get_origin(tp) def is_union(tp: Optional[Type[Any]]) -> bool: if sys.version_info < (3, 10): return tp is Union # type: ignore[comparison-overlap] else: import types return tp is Union or tp is types.UnionType # type: ignore[comparison-overlap] def is_typeddict(tp: Type[Any]) -> bool: return typing_extensions.is_typeddict(tp) def is_literal_type(tp: Type[Any]) -> bool: return get_origin(tp) in _LITERAL_TYPES def parse_date(value: Union[date, StrBytesIntFloat]) -> date: return _parse_date(value) def parse_datetime(value: Union[datetime, StrBytesIntFloat]) -> datetime: return _parse_datetime(value) ================================================ FILE: src/openai/_utils/_datetime_parse.py ================================================ """ This file contains code from https://github.com/pydantic/pydantic/blob/main/pydantic/v1/datetime_parse.py without the Pydantic v1 specific errors. """ from __future__ import annotations import re from typing import Dict, Union, Optional from datetime import date, datetime, timezone, timedelta from .._types import StrBytesIntFloat date_expr = r"(?P\d{4})-(?P\d{1,2})-(?P\d{1,2})" time_expr = ( r"(?P\d{1,2}):(?P\d{1,2})" r"(?::(?P\d{1,2})(?:\.(?P\d{1,6})\d{0,6})?)?" r"(?PZ|[+-]\d{2}(?::?\d{2})?)?$" ) date_re = re.compile(f"{date_expr}$") datetime_re = re.compile(f"{date_expr}[T ]{time_expr}") EPOCH = datetime(1970, 1, 1) # if greater than this, the number is in ms, if less than or equal it's in seconds # (in seconds this is 11th October 2603, in ms it's 20th August 1970) MS_WATERSHED = int(2e10) # slightly more than datetime.max in ns - (datetime.max - EPOCH).total_seconds() * 1e9 MAX_NUMBER = int(3e20) def _get_numeric(value: StrBytesIntFloat, native_expected_type: str) -> Union[None, int, float]: if isinstance(value, (int, float)): return value try: return float(value) except ValueError: return None except TypeError: raise TypeError(f"invalid type; expected {native_expected_type}, string, bytes, int or float") from None def _from_unix_seconds(seconds: Union[int, float]) -> datetime: if seconds > MAX_NUMBER: return datetime.max elif seconds < -MAX_NUMBER: return datetime.min while abs(seconds) > MS_WATERSHED: seconds /= 1000 dt = EPOCH + timedelta(seconds=seconds) return dt.replace(tzinfo=timezone.utc) def _parse_timezone(value: Optional[str]) -> Union[None, int, timezone]: if value == "Z": return timezone.utc elif value is not None: offset_mins = int(value[-2:]) if len(value) > 3 else 0 offset = 60 * int(value[1:3]) + offset_mins if value[0] == "-": offset = -offset return timezone(timedelta(minutes=offset)) else: return None def parse_datetime(value: Union[datetime, StrBytesIntFloat]) -> datetime: """ Parse a datetime/int/float/string and return a datetime.datetime. This function supports time zone offsets. When the input contains one, the output uses a timezone with a fixed offset from UTC. Raise ValueError if the input is well formatted but not a valid datetime. Raise ValueError if the input isn't well formatted. """ if isinstance(value, datetime): return value number = _get_numeric(value, "datetime") if number is not None: return _from_unix_seconds(number) if isinstance(value, bytes): value = value.decode() assert not isinstance(value, (float, int)) match = datetime_re.match(value) if match is None: raise ValueError("invalid datetime format") kw = match.groupdict() if kw["microsecond"]: kw["microsecond"] = kw["microsecond"].ljust(6, "0") tzinfo = _parse_timezone(kw.pop("tzinfo")) kw_: Dict[str, Union[None, int, timezone]] = {k: int(v) for k, v in kw.items() if v is not None} kw_["tzinfo"] = tzinfo return datetime(**kw_) # type: ignore def parse_date(value: Union[date, StrBytesIntFloat]) -> date: """ Parse a date/int/float/string and return a datetime.date. Raise ValueError if the input is well formatted but not a valid date. Raise ValueError if the input isn't well formatted. """ if isinstance(value, date): if isinstance(value, datetime): return value.date() else: return value number = _get_numeric(value, "date") if number is not None: return _from_unix_seconds(number).date() if isinstance(value, bytes): value = value.decode() assert not isinstance(value, (float, int)) match = date_re.match(value) if match is None: raise ValueError("invalid date format") kw = {k: int(v) for k, v in match.groupdict().items()} try: return date(**kw) except ValueError: raise ValueError("invalid date format") from None ================================================ FILE: src/openai/_utils/_json.py ================================================ import json from typing import Any from datetime import datetime from typing_extensions import override import pydantic from .._compat import model_dump def openapi_dumps(obj: Any) -> bytes: """ Serialize an object to UTF-8 encoded JSON bytes. Extends the standard json.dumps with support for additional types commonly used in the SDK, such as `datetime`, `pydantic.BaseModel`, etc. """ return json.dumps( obj, cls=_CustomEncoder, # Uses the same defaults as httpx's JSON serialization ensure_ascii=False, separators=(",", ":"), allow_nan=False, ).encode() class _CustomEncoder(json.JSONEncoder): @override def default(self, o: Any) -> Any: if isinstance(o, datetime): return o.isoformat() if isinstance(o, pydantic.BaseModel): return model_dump(o, exclude_unset=True, mode="json", by_alias=True) return super().default(o) ================================================ FILE: src/openai/_utils/_logs.py ================================================ import os import logging from typing_extensions import override from ._utils import is_dict logger: logging.Logger = logging.getLogger("openai") httpx_logger: logging.Logger = logging.getLogger("httpx") SENSITIVE_HEADERS = {"api-key", "authorization"} def _basic_config() -> None: # e.g. [2023-10-05 14:12:26 - openai._base_client:818 - DEBUG] HTTP Request: POST http://127.0.0.1:4010/foo/bar "200 OK" logging.basicConfig( format="[%(asctime)s - %(name)s:%(lineno)d - %(levelname)s] %(message)s", datefmt="%Y-%m-%d %H:%M:%S", ) def setup_logging() -> None: env = os.environ.get("OPENAI_LOG") if env == "debug": _basic_config() logger.setLevel(logging.DEBUG) httpx_logger.setLevel(logging.DEBUG) elif env == "info": _basic_config() logger.setLevel(logging.INFO) httpx_logger.setLevel(logging.INFO) class SensitiveHeadersFilter(logging.Filter): @override def filter(self, record: logging.LogRecord) -> bool: if is_dict(record.args) and "headers" in record.args and is_dict(record.args["headers"]): headers = record.args["headers"] = {**record.args["headers"]} for header in headers: if str(header).lower() in SENSITIVE_HEADERS: headers[header] = "" return True ================================================ FILE: src/openai/_utils/_proxy.py ================================================ from __future__ import annotations from abc import ABC, abstractmethod from typing import Generic, TypeVar, Iterable, cast from typing_extensions import override T = TypeVar("T") class LazyProxy(Generic[T], ABC): """Implements data methods to pretend that an instance is another instance. This includes forwarding attribute access and other methods. """ # Note: we have to special case proxies that themselves return proxies # to support using a proxy as a catch-all for any random access, e.g. `proxy.foo.bar.baz` def __getattr__(self, attr: str) -> object: proxied = self.__get_proxied__() if isinstance(proxied, LazyProxy): return proxied # pyright: ignore return getattr(proxied, attr) @override def __repr__(self) -> str: proxied = self.__get_proxied__() if isinstance(proxied, LazyProxy): return proxied.__class__.__name__ return repr(self.__get_proxied__()) @override def __str__(self) -> str: proxied = self.__get_proxied__() if isinstance(proxied, LazyProxy): return proxied.__class__.__name__ return str(proxied) @override def __dir__(self) -> Iterable[str]: proxied = self.__get_proxied__() if isinstance(proxied, LazyProxy): return [] return proxied.__dir__() @property # type: ignore @override def __class__(self) -> type: # pyright: ignore try: proxied = self.__get_proxied__() except Exception: return type(self) if issubclass(type(proxied), LazyProxy): return type(proxied) return proxied.__class__ def __get_proxied__(self) -> T: return self.__load__() def __as_proxied__(self) -> T: """Helper method that returns the current proxy, typed as the loaded object""" return cast(T, self) @abstractmethod def __load__(self) -> T: ... ================================================ FILE: src/openai/_utils/_reflection.py ================================================ from __future__ import annotations import inspect from typing import Any, Callable def function_has_argument(func: Callable[..., Any], arg_name: str) -> bool: """Returns whether or not the given function has a specific parameter""" sig = inspect.signature(func) return arg_name in sig.parameters def assert_signatures_in_sync( source_func: Callable[..., Any], check_func: Callable[..., Any], *, exclude_params: set[str] = set(), description: str = "", ) -> None: """Ensure that the signature of the second function matches the first.""" check_sig = inspect.signature(check_func) source_sig = inspect.signature(source_func) errors: list[str] = [] for name, source_param in source_sig.parameters.items(): if name in exclude_params: continue custom_param = check_sig.parameters.get(name) if not custom_param: errors.append(f"the `{name}` param is missing") continue if custom_param.annotation != source_param.annotation: errors.append( f"types for the `{name}` param are do not match; source={repr(source_param.annotation)} checking={repr(custom_param.annotation)}" ) continue if errors: raise AssertionError( f"{len(errors)} errors encountered when comparing signatures{description}:\n\n" + "\n\n".join(errors) ) ================================================ FILE: src/openai/_utils/_resources_proxy.py ================================================ from __future__ import annotations from typing import Any from typing_extensions import override from ._proxy import LazyProxy class ResourcesProxy(LazyProxy[Any]): """A proxy for the `openai.resources` module. This is used so that we can lazily import `openai.resources` only when needed *and* so that users can just import `openai` and reference `openai.resources` """ @override def __load__(self) -> Any: import importlib mod = importlib.import_module("openai.resources") return mod resources = ResourcesProxy().__as_proxied__() ================================================ FILE: src/openai/_utils/_streams.py ================================================ from typing import Any from typing_extensions import Iterator, AsyncIterator def consume_sync_iterator(iterator: Iterator[Any]) -> None: for _ in iterator: ... async def consume_async_iterator(iterator: AsyncIterator[Any]) -> None: async for _ in iterator: ... ================================================ FILE: src/openai/_utils/_sync.py ================================================ from __future__ import annotations import asyncio import functools from typing import TypeVar, Callable, Awaitable from typing_extensions import ParamSpec import anyio import sniffio import anyio.to_thread T_Retval = TypeVar("T_Retval") T_ParamSpec = ParamSpec("T_ParamSpec") async def to_thread( func: Callable[T_ParamSpec, T_Retval], /, *args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs ) -> T_Retval: if sniffio.current_async_library() == "asyncio": return await asyncio.to_thread(func, *args, **kwargs) return await anyio.to_thread.run_sync( functools.partial(func, *args, **kwargs), ) # inspired by `asyncer`, https://github.com/tiangolo/asyncer def asyncify(function: Callable[T_ParamSpec, T_Retval]) -> Callable[T_ParamSpec, Awaitable[T_Retval]]: """ Take a blocking function and create an async one that receives the same positional and keyword arguments. Usage: ```python def blocking_func(arg1, arg2, kwarg1=None): # blocking code return result result = asyncify(blocking_function)(arg1, arg2, kwarg1=value1) ``` ## Arguments `function`: a blocking regular callable (e.g. a function) ## Return An async function that takes the same positional and keyword arguments as the original one, that when called runs the same original function in a thread worker and returns the result. """ async def wrapper(*args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs) -> T_Retval: return await to_thread(function, *args, **kwargs) return wrapper ================================================ FILE: src/openai/_utils/_transform.py ================================================ from __future__ import annotations import io import base64 import pathlib from typing import Any, Mapping, TypeVar, cast from datetime import date, datetime from typing_extensions import Literal, get_args, override, get_type_hints as _get_type_hints import anyio import pydantic from ._utils import ( is_list, is_given, lru_cache, is_mapping, is_iterable, is_sequence, ) from .._files import is_base64_file_input from ._compat import get_origin, is_typeddict from ._typing import ( is_list_type, is_union_type, extract_type_arg, is_iterable_type, is_required_type, is_sequence_type, is_annotated_type, strip_annotated_type, ) _T = TypeVar("_T") # TODO: support for drilling globals() and locals() # TODO: ensure works correctly with forward references in all cases PropertyFormat = Literal["iso8601", "base64", "custom"] class PropertyInfo: """Metadata class to be used in Annotated types to provide information about a given type. For example: class MyParams(TypedDict): account_holder_name: Annotated[str, PropertyInfo(alias='accountHolderName')] This means that {'account_holder_name': 'Robert'} will be transformed to {'accountHolderName': 'Robert'} before being sent to the API. """ alias: str | None format: PropertyFormat | None format_template: str | None discriminator: str | None def __init__( self, *, alias: str | None = None, format: PropertyFormat | None = None, format_template: str | None = None, discriminator: str | None = None, ) -> None: self.alias = alias self.format = format self.format_template = format_template self.discriminator = discriminator @override def __repr__(self) -> str: return f"{self.__class__.__name__}(alias='{self.alias}', format={self.format}, format_template='{self.format_template}', discriminator='{self.discriminator}')" def maybe_transform( data: object, expected_type: object, ) -> Any | None: """Wrapper over `transform()` that allows `None` to be passed. See `transform()` for more details. """ if data is None: return None return transform(data, expected_type) # Wrapper over _transform_recursive providing fake types def transform( data: _T, expected_type: object, ) -> _T: """Transform dictionaries based off of type information from the given type, for example: ```py class Params(TypedDict, total=False): card_id: Required[Annotated[str, PropertyInfo(alias="cardID")]] transformed = transform({"card_id": ""}, Params) # {'cardID': ''} ``` Any keys / data that does not have type information given will be included as is. It should be noted that the transformations that this function does are not represented in the type system. """ transformed = _transform_recursive(data, annotation=cast(type, expected_type)) return cast(_T, transformed) @lru_cache(maxsize=8096) def _get_annotated_type(type_: type) -> type | None: """If the given type is an `Annotated` type then it is returned, if not `None` is returned. This also unwraps the type when applicable, e.g. `Required[Annotated[T, ...]]` """ if is_required_type(type_): # Unwrap `Required[Annotated[T, ...]]` to `Annotated[T, ...]` type_ = get_args(type_)[0] if is_annotated_type(type_): return type_ return None def _maybe_transform_key(key: str, type_: type) -> str: """Transform the given `data` based on the annotations provided in `type_`. Note: this function only looks at `Annotated` types that contain `PropertyInfo` metadata. """ annotated_type = _get_annotated_type(type_) if annotated_type is None: # no `Annotated` definition for this type, no transformation needed return key # ignore the first argument as it is the actual type annotations = get_args(annotated_type)[1:] for annotation in annotations: if isinstance(annotation, PropertyInfo) and annotation.alias is not None: return annotation.alias return key def _no_transform_needed(annotation: type) -> bool: return annotation == float or annotation == int def _transform_recursive( data: object, *, annotation: type, inner_type: type | None = None, ) -> object: """Transform the given data against the expected type. Args: annotation: The direct type annotation given to the particular piece of data. This may or may not be wrapped in metadata types, e.g. `Required[T]`, `Annotated[T, ...]` etc inner_type: If applicable, this is the "inside" type. This is useful in certain cases where the outside type is a container type such as `List[T]`. In that case `inner_type` should be set to `T` so that each entry in the list can be transformed using the metadata from the container type. Defaults to the same value as the `annotation` argument. """ from .._compat import model_dump if inner_type is None: inner_type = annotation stripped_type = strip_annotated_type(inner_type) origin = get_origin(stripped_type) or stripped_type if is_typeddict(stripped_type) and is_mapping(data): return _transform_typeddict(data, stripped_type) if origin == dict and is_mapping(data): items_type = get_args(stripped_type)[1] return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()} if ( # List[T] (is_list_type(stripped_type) and is_list(data)) # Iterable[T] or (is_iterable_type(stripped_type) and is_iterable(data) and not isinstance(data, str)) # Sequence[T] or (is_sequence_type(stripped_type) and is_sequence(data) and not isinstance(data, str)) ): # dicts are technically iterable, but it is an iterable on the keys of the dict and is not usually # intended as an iterable, so we don't transform it. if isinstance(data, dict): return cast(object, data) inner_type = extract_type_arg(stripped_type, 0) if _no_transform_needed(inner_type): # for some types there is no need to transform anything, so we can get a small # perf boost from skipping that work. # # but we still need to convert to a list to ensure the data is json-serializable if is_list(data): return data return list(data) return [_transform_recursive(d, annotation=annotation, inner_type=inner_type) for d in data] if is_union_type(stripped_type): # For union types we run the transformation against all subtypes to ensure that everything is transformed. # # TODO: there may be edge cases where the same normalized field name will transform to two different names # in different subtypes. for subtype in get_args(stripped_type): data = _transform_recursive(data, annotation=annotation, inner_type=subtype) return data if isinstance(data, pydantic.BaseModel): return model_dump(data, exclude_unset=True, mode="json", exclude=getattr(data, "__api_exclude__", None)) annotated_type = _get_annotated_type(annotation) if annotated_type is None: return data # ignore the first argument as it is the actual type annotations = get_args(annotated_type)[1:] for annotation in annotations: if isinstance(annotation, PropertyInfo) and annotation.format is not None: return _format_data(data, annotation.format, annotation.format_template) return data def _format_data(data: object, format_: PropertyFormat, format_template: str | None) -> object: if isinstance(data, (date, datetime)): if format_ == "iso8601": return data.isoformat() if format_ == "custom" and format_template is not None: return data.strftime(format_template) if format_ == "base64" and is_base64_file_input(data): binary: str | bytes | None = None if isinstance(data, pathlib.Path): binary = data.read_bytes() elif isinstance(data, io.IOBase): binary = data.read() if isinstance(binary, str): # type: ignore[unreachable] binary = binary.encode() if not isinstance(binary, bytes): raise RuntimeError(f"Could not read bytes from {data}; Received {type(binary)}") return base64.b64encode(binary).decode("ascii") return data def _transform_typeddict( data: Mapping[str, object], expected_type: type, ) -> Mapping[str, object]: result: dict[str, object] = {} annotations = get_type_hints(expected_type, include_extras=True) for key, value in data.items(): if not is_given(value): # we don't need to include omitted values here as they'll # be stripped out before the request is sent anyway continue type_ = annotations.get(key) if type_ is None: # we do not have a type annotation for this field, leave it as is result[key] = value else: result[_maybe_transform_key(key, type_)] = _transform_recursive(value, annotation=type_) return result async def async_maybe_transform( data: object, expected_type: object, ) -> Any | None: """Wrapper over `async_transform()` that allows `None` to be passed. See `async_transform()` for more details. """ if data is None: return None return await async_transform(data, expected_type) async def async_transform( data: _T, expected_type: object, ) -> _T: """Transform dictionaries based off of type information from the given type, for example: ```py class Params(TypedDict, total=False): card_id: Required[Annotated[str, PropertyInfo(alias="cardID")]] transformed = transform({"card_id": ""}, Params) # {'cardID': ''} ``` Any keys / data that does not have type information given will be included as is. It should be noted that the transformations that this function does are not represented in the type system. """ transformed = await _async_transform_recursive(data, annotation=cast(type, expected_type)) return cast(_T, transformed) async def _async_transform_recursive( data: object, *, annotation: type, inner_type: type | None = None, ) -> object: """Transform the given data against the expected type. Args: annotation: The direct type annotation given to the particular piece of data. This may or may not be wrapped in metadata types, e.g. `Required[T]`, `Annotated[T, ...]` etc inner_type: If applicable, this is the "inside" type. This is useful in certain cases where the outside type is a container type such as `List[T]`. In that case `inner_type` should be set to `T` so that each entry in the list can be transformed using the metadata from the container type. Defaults to the same value as the `annotation` argument. """ from .._compat import model_dump if inner_type is None: inner_type = annotation stripped_type = strip_annotated_type(inner_type) origin = get_origin(stripped_type) or stripped_type if is_typeddict(stripped_type) and is_mapping(data): return await _async_transform_typeddict(data, stripped_type) if origin == dict and is_mapping(data): items_type = get_args(stripped_type)[1] return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()} if ( # List[T] (is_list_type(stripped_type) and is_list(data)) # Iterable[T] or (is_iterable_type(stripped_type) and is_iterable(data) and not isinstance(data, str)) # Sequence[T] or (is_sequence_type(stripped_type) and is_sequence(data) and not isinstance(data, str)) ): # dicts are technically iterable, but it is an iterable on the keys of the dict and is not usually # intended as an iterable, so we don't transform it. if isinstance(data, dict): return cast(object, data) inner_type = extract_type_arg(stripped_type, 0) if _no_transform_needed(inner_type): # for some types there is no need to transform anything, so we can get a small # perf boost from skipping that work. # # but we still need to convert to a list to ensure the data is json-serializable if is_list(data): return data return list(data) return [await _async_transform_recursive(d, annotation=annotation, inner_type=inner_type) for d in data] if is_union_type(stripped_type): # For union types we run the transformation against all subtypes to ensure that everything is transformed. # # TODO: there may be edge cases where the same normalized field name will transform to two different names # in different subtypes. for subtype in get_args(stripped_type): data = await _async_transform_recursive(data, annotation=annotation, inner_type=subtype) return data if isinstance(data, pydantic.BaseModel): return model_dump(data, exclude_unset=True, mode="json") annotated_type = _get_annotated_type(annotation) if annotated_type is None: return data # ignore the first argument as it is the actual type annotations = get_args(annotated_type)[1:] for annotation in annotations: if isinstance(annotation, PropertyInfo) and annotation.format is not None: return await _async_format_data(data, annotation.format, annotation.format_template) return data async def _async_format_data(data: object, format_: PropertyFormat, format_template: str | None) -> object: if isinstance(data, (date, datetime)): if format_ == "iso8601": return data.isoformat() if format_ == "custom" and format_template is not None: return data.strftime(format_template) if format_ == "base64" and is_base64_file_input(data): binary: str | bytes | None = None if isinstance(data, pathlib.Path): binary = await anyio.Path(data).read_bytes() elif isinstance(data, io.IOBase): binary = data.read() if isinstance(binary, str): # type: ignore[unreachable] binary = binary.encode() if not isinstance(binary, bytes): raise RuntimeError(f"Could not read bytes from {data}; Received {type(binary)}") return base64.b64encode(binary).decode("ascii") return data async def _async_transform_typeddict( data: Mapping[str, object], expected_type: type, ) -> Mapping[str, object]: result: dict[str, object] = {} annotations = get_type_hints(expected_type, include_extras=True) for key, value in data.items(): if not is_given(value): # we don't need to include omitted values here as they'll # be stripped out before the request is sent anyway continue type_ = annotations.get(key) if type_ is None: # we do not have a type annotation for this field, leave it as is result[key] = value else: result[_maybe_transform_key(key, type_)] = await _async_transform_recursive(value, annotation=type_) return result @lru_cache(maxsize=8096) def get_type_hints( obj: Any, globalns: dict[str, Any] | None = None, localns: Mapping[str, Any] | None = None, include_extras: bool = False, ) -> dict[str, Any]: return _get_type_hints(obj, globalns=globalns, localns=localns, include_extras=include_extras) ================================================ FILE: src/openai/_utils/_typing.py ================================================ from __future__ import annotations import sys import typing import typing_extensions from typing import Any, TypeVar, Iterable, cast from collections import abc as _c_abc from typing_extensions import ( TypeIs, Required, Annotated, get_args, get_origin, ) from ._utils import lru_cache from .._types import InheritsGeneric from ._compat import is_union as _is_union def is_annotated_type(typ: type) -> bool: return get_origin(typ) == Annotated def is_list_type(typ: type) -> bool: return (get_origin(typ) or typ) == list def is_sequence_type(typ: type) -> bool: origin = get_origin(typ) or typ return origin == typing_extensions.Sequence or origin == typing.Sequence or origin == _c_abc.Sequence def is_iterable_type(typ: type) -> bool: """If the given type is `typing.Iterable[T]`""" origin = get_origin(typ) or typ return origin == Iterable or origin == _c_abc.Iterable def is_union_type(typ: type) -> bool: return _is_union(get_origin(typ)) def is_required_type(typ: type) -> bool: return get_origin(typ) == Required def is_typevar(typ: type) -> bool: # type ignore is required because type checkers # think this expression will always return False return type(typ) == TypeVar # type: ignore _TYPE_ALIAS_TYPES: tuple[type[typing_extensions.TypeAliasType], ...] = (typing_extensions.TypeAliasType,) if sys.version_info >= (3, 12): _TYPE_ALIAS_TYPES = (*_TYPE_ALIAS_TYPES, typing.TypeAliasType) def is_type_alias_type(tp: Any, /) -> TypeIs[typing_extensions.TypeAliasType]: """Return whether the provided argument is an instance of `TypeAliasType`. ```python type Int = int is_type_alias_type(Int) # > True Str = TypeAliasType("Str", str) is_type_alias_type(Str) # > True ``` """ return isinstance(tp, _TYPE_ALIAS_TYPES) # Extracts T from Annotated[T, ...] or from Required[Annotated[T, ...]] @lru_cache(maxsize=8096) def strip_annotated_type(typ: type) -> type: if is_required_type(typ) or is_annotated_type(typ): return strip_annotated_type(cast(type, get_args(typ)[0])) return typ def extract_type_arg(typ: type, index: int) -> type: args = get_args(typ) try: return cast(type, args[index]) except IndexError as err: raise RuntimeError(f"Expected type {typ} to have a type argument at index {index} but it did not") from err def extract_type_var_from_base( typ: type, *, generic_bases: tuple[type, ...], index: int, failure_message: str | None = None, ) -> type: """Given a type like `Foo[T]`, returns the generic type variable `T`. This also handles the case where a concrete subclass is given, e.g. ```py class MyResponse(Foo[bytes]): ... extract_type_var(MyResponse, bases=(Foo,), index=0) -> bytes ``` And where a generic subclass is given: ```py _T = TypeVar('_T') class MyResponse(Foo[_T]): ... extract_type_var(MyResponse[bytes], bases=(Foo,), index=0) -> bytes ``` """ cls = cast(object, get_origin(typ) or typ) if cls in generic_bases: # pyright: ignore[reportUnnecessaryContains] # we're given the class directly return extract_type_arg(typ, index) # if a subclass is given # --- # this is needed as __orig_bases__ is not present in the typeshed stubs # because it is intended to be for internal use only, however there does # not seem to be a way to resolve generic TypeVars for inherited subclasses # without using it. if isinstance(cls, InheritsGeneric): target_base_class: Any | None = None for base in cls.__orig_bases__: if base.__origin__ in generic_bases: target_base_class = base break if target_base_class is None: raise RuntimeError( "Could not find the generic base class;\n" "This should never happen;\n" f"Does {cls} inherit from one of {generic_bases} ?" ) extracted = extract_type_arg(target_base_class, index) if is_typevar(extracted): # If the extracted type argument is itself a type variable # then that means the subclass itself is generic, so we have # to resolve the type argument from the class itself, not # the base class. # # Note: if there is more than 1 type argument, the subclass could # change the ordering of the type arguments, this is not currently # supported. return extract_type_arg(typ, index) return extracted raise RuntimeError(failure_message or f"Could not resolve inner type variable at index {index} for {typ}") ================================================ FILE: src/openai/_utils/_utils.py ================================================ from __future__ import annotations import os import re import inspect import functools from typing import ( TYPE_CHECKING, Any, Tuple, Mapping, TypeVar, Callable, Iterable, Sequence, cast, overload, ) from pathlib import Path from datetime import date, datetime from typing_extensions import TypeGuard import sniffio from .._types import Omit, NotGiven, FileTypes, HeadersLike _T = TypeVar("_T") _TupleT = TypeVar("_TupleT", bound=Tuple[object, ...]) _MappingT = TypeVar("_MappingT", bound=Mapping[str, object]) _SequenceT = TypeVar("_SequenceT", bound=Sequence[object]) CallableT = TypeVar("CallableT", bound=Callable[..., Any]) if TYPE_CHECKING: from ..lib.azure import AzureOpenAI, AsyncAzureOpenAI def flatten(t: Iterable[Iterable[_T]]) -> list[_T]: return [item for sublist in t for item in sublist] def extract_files( # TODO: this needs to take Dict but variance issues..... # create protocol type ? query: Mapping[str, object], *, paths: Sequence[Sequence[str]], ) -> list[tuple[str, FileTypes]]: """Recursively extract files from the given dictionary based on specified paths. A path may look like this ['foo', 'files', '', 'data']. Note: this mutates the given dictionary. """ files: list[tuple[str, FileTypes]] = [] for path in paths: files.extend(_extract_items(query, path, index=0, flattened_key=None)) return files def _extract_items( obj: object, path: Sequence[str], *, index: int, flattened_key: str | None, ) -> list[tuple[str, FileTypes]]: try: key = path[index] except IndexError: if not is_given(obj): # no value was provided - we can safely ignore return [] # cyclical import from .._files import assert_is_file_content # We have exhausted the path, return the entry we found. assert flattened_key is not None if is_list(obj): files: list[tuple[str, FileTypes]] = [] for entry in obj: assert_is_file_content(entry, key=flattened_key + "[]" if flattened_key else "") files.append((flattened_key + "[]", cast(FileTypes, entry))) return files assert_is_file_content(obj, key=flattened_key) return [(flattened_key, cast(FileTypes, obj))] index += 1 if is_dict(obj): try: # We are at the last entry in the path so we must remove the field if (len(path)) == index: item = obj.pop(key) else: item = obj[key] except KeyError: # Key was not present in the dictionary, this is not indicative of an error # as the given path may not point to a required field. We also do not want # to enforce required fields as the API may differ from the spec in some cases. return [] if flattened_key is None: flattened_key = key else: flattened_key += f"[{key}]" return _extract_items( item, path, index=index, flattened_key=flattened_key, ) elif is_list(obj): if key != "": return [] return flatten( [ _extract_items( item, path, index=index, flattened_key=flattened_key + "[]" if flattened_key is not None else "[]", ) for item in obj ] ) # Something unexpected was passed, just ignore it. return [] def is_given(obj: _T | NotGiven | Omit) -> TypeGuard[_T]: return not isinstance(obj, NotGiven) and not isinstance(obj, Omit) # Type safe methods for narrowing types with TypeVars. # The default narrowing for isinstance(obj, dict) is dict[unknown, unknown], # however this cause Pyright to rightfully report errors. As we know we don't # care about the contained types we can safely use `object` in its place. # # There are two separate functions defined, `is_*` and `is_*_t` for different use cases. # `is_*` is for when you're dealing with an unknown input # `is_*_t` is for when you're narrowing a known union type to a specific subset def is_tuple(obj: object) -> TypeGuard[tuple[object, ...]]: return isinstance(obj, tuple) def is_tuple_t(obj: _TupleT | object) -> TypeGuard[_TupleT]: return isinstance(obj, tuple) def is_sequence(obj: object) -> TypeGuard[Sequence[object]]: return isinstance(obj, Sequence) def is_sequence_t(obj: _SequenceT | object) -> TypeGuard[_SequenceT]: return isinstance(obj, Sequence) def is_mapping(obj: object) -> TypeGuard[Mapping[str, object]]: return isinstance(obj, Mapping) def is_mapping_t(obj: _MappingT | object) -> TypeGuard[_MappingT]: return isinstance(obj, Mapping) def is_dict(obj: object) -> TypeGuard[dict[object, object]]: return isinstance(obj, dict) def is_list(obj: object) -> TypeGuard[list[object]]: return isinstance(obj, list) def is_iterable(obj: object) -> TypeGuard[Iterable[object]]: return isinstance(obj, Iterable) def deepcopy_minimal(item: _T) -> _T: """Minimal reimplementation of copy.deepcopy() that will only copy certain object types: - mappings, e.g. `dict` - list This is done for performance reasons. """ if is_mapping(item): return cast(_T, {k: deepcopy_minimal(v) for k, v in item.items()}) if is_list(item): return cast(_T, [deepcopy_minimal(entry) for entry in item]) return item # copied from https://github.com/Rapptz/RoboDanny def human_join(seq: Sequence[str], *, delim: str = ", ", final: str = "or") -> str: size = len(seq) if size == 0: return "" if size == 1: return seq[0] if size == 2: return f"{seq[0]} {final} {seq[1]}" return delim.join(seq[:-1]) + f" {final} {seq[-1]}" def quote(string: str) -> str: """Add single quotation marks around the given string. Does *not* do any escaping.""" return f"'{string}'" def required_args(*variants: Sequence[str]) -> Callable[[CallableT], CallableT]: """Decorator to enforce a given set of arguments or variants of arguments are passed to the decorated function. Useful for enforcing runtime validation of overloaded functions. Example usage: ```py @overload def foo(*, a: str) -> str: ... @overload def foo(*, b: bool) -> str: ... # This enforces the same constraints that a static type checker would # i.e. that either a or b must be passed to the function @required_args(["a"], ["b"]) def foo(*, a: str | None = None, b: bool | None = None) -> str: ... ``` """ def inner(func: CallableT) -> CallableT: params = inspect.signature(func).parameters positional = [ name for name, param in params.items() if param.kind in { param.POSITIONAL_ONLY, param.POSITIONAL_OR_KEYWORD, } ] @functools.wraps(func) def wrapper(*args: object, **kwargs: object) -> object: given_params: set[str] = set() for i, _ in enumerate(args): try: given_params.add(positional[i]) except IndexError: raise TypeError( f"{func.__name__}() takes {len(positional)} argument(s) but {len(args)} were given" ) from None for key in kwargs.keys(): given_params.add(key) for variant in variants: matches = all((param in given_params for param in variant)) if matches: break else: # no break if len(variants) > 1: variations = human_join( ["(" + human_join([quote(arg) for arg in variant], final="and") + ")" for variant in variants] ) msg = f"Missing required arguments; Expected either {variations} arguments to be given" else: assert len(variants) > 0 # TODO: this error message is not deterministic missing = list(set(variants[0]) - given_params) if len(missing) > 1: msg = f"Missing required arguments: {human_join([quote(arg) for arg in missing])}" else: msg = f"Missing required argument: {quote(missing[0])}" raise TypeError(msg) return func(*args, **kwargs) return wrapper # type: ignore return inner _K = TypeVar("_K") _V = TypeVar("_V") @overload def strip_not_given(obj: None) -> None: ... @overload def strip_not_given(obj: Mapping[_K, _V | NotGiven]) -> dict[_K, _V]: ... @overload def strip_not_given(obj: object) -> object: ... def strip_not_given(obj: object | None) -> object: """Remove all top-level keys where their values are instances of `NotGiven`""" if obj is None: return None if not is_mapping(obj): return obj return {key: value for key, value in obj.items() if not isinstance(value, NotGiven)} def coerce_integer(val: str) -> int: return int(val, base=10) def coerce_float(val: str) -> float: return float(val) def coerce_boolean(val: str) -> bool: return val == "true" or val == "1" or val == "on" def maybe_coerce_integer(val: str | None) -> int | None: if val is None: return None return coerce_integer(val) def maybe_coerce_float(val: str | None) -> float | None: if val is None: return None return coerce_float(val) def maybe_coerce_boolean(val: str | None) -> bool | None: if val is None: return None return coerce_boolean(val) def removeprefix(string: str, prefix: str) -> str: """Remove a prefix from a string. Backport of `str.removeprefix` for Python < 3.9 """ if string.startswith(prefix): return string[len(prefix) :] return string def removesuffix(string: str, suffix: str) -> str: """Remove a suffix from a string. Backport of `str.removesuffix` for Python < 3.9 """ if string.endswith(suffix): return string[: -len(suffix)] return string def file_from_path(path: str) -> FileTypes: contents = Path(path).read_bytes() file_name = os.path.basename(path) return (file_name, contents) def get_required_header(headers: HeadersLike, header: str) -> str: lower_header = header.lower() if is_mapping_t(headers): # mypy doesn't understand the type narrowing here for k, v in headers.items(): # type: ignore if k.lower() == lower_header and isinstance(v, str): return v # to deal with the case where the header looks like Stainless-Event-Id intercaps_header = re.sub(r"([^\w])(\w)", lambda pat: pat.group(1) + pat.group(2).upper(), header.capitalize()) for normalized_header in [header, lower_header, header.upper(), intercaps_header]: value = headers.get(normalized_header) if value: return value raise ValueError(f"Could not find {header} header") def get_async_library() -> str: try: return sniffio.current_async_library() except Exception: return "false" def lru_cache(*, maxsize: int | None = 128) -> Callable[[CallableT], CallableT]: """A version of functools.lru_cache that retains the type signature for the wrapped function arguments. """ wrapper = functools.lru_cache( # noqa: TID251 maxsize=maxsize, ) return cast(Any, wrapper) # type: ignore[no-any-return] def json_safe(data: object) -> object: """Translates a mapping / sequence recursively in the same fashion as `pydantic` v2's `model_dump(mode="json")`. """ if is_mapping(data): return {json_safe(key): json_safe(value) for key, value in data.items()} if is_iterable(data) and not isinstance(data, (str, bytes, bytearray)): return [json_safe(item) for item in data] if isinstance(data, (datetime, date)): return data.isoformat() return data def is_azure_client(client: object) -> TypeGuard[AzureOpenAI]: from ..lib.azure import AzureOpenAI return isinstance(client, AzureOpenAI) def is_async_azure_client(client: object) -> TypeGuard[AsyncAzureOpenAI]: from ..lib.azure import AsyncAzureOpenAI return isinstance(client, AsyncAzureOpenAI) ================================================ FILE: src/openai/_version.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "openai" __version__ = "2.29.0" # x-release-please-version ================================================ FILE: src/openai/cli/__init__.py ================================================ from ._cli import main as main ================================================ FILE: src/openai/cli/_api/__init__.py ================================================ from ._main import register_commands as register_commands ================================================ FILE: src/openai/cli/_api/_main.py ================================================ from __future__ import annotations from argparse import ArgumentParser from . import chat, audio, files, image, models, completions, fine_tuning def register_commands(parser: ArgumentParser) -> None: subparsers = parser.add_subparsers(help="All API subcommands") chat.register(subparsers) image.register(subparsers) audio.register(subparsers) files.register(subparsers) models.register(subparsers) completions.register(subparsers) fine_tuning.register(subparsers) ================================================ FILE: src/openai/cli/_api/audio.py ================================================ from __future__ import annotations import sys from typing import TYPE_CHECKING, Any, Optional, cast from argparse import ArgumentParser from .._utils import get_client, print_model from ..._types import omit from .._models import BaseModel from .._progress import BufferReader from ...types.audio import Transcription if TYPE_CHECKING: from argparse import _SubParsersAction def register(subparser: _SubParsersAction[ArgumentParser]) -> None: # transcriptions sub = subparser.add_parser("audio.transcriptions.create") # Required sub.add_argument("-m", "--model", type=str, default="whisper-1") sub.add_argument("-f", "--file", type=str, required=True) # Optional sub.add_argument("--response-format", type=str) sub.add_argument("--language", type=str) sub.add_argument("-t", "--temperature", type=float) sub.add_argument("--prompt", type=str) sub.set_defaults(func=CLIAudio.transcribe, args_model=CLITranscribeArgs) # translations sub = subparser.add_parser("audio.translations.create") # Required sub.add_argument("-f", "--file", type=str, required=True) # Optional sub.add_argument("-m", "--model", type=str, default="whisper-1") sub.add_argument("--response-format", type=str) # TODO: doesn't seem to be supported by the API # sub.add_argument("--language", type=str) sub.add_argument("-t", "--temperature", type=float) sub.add_argument("--prompt", type=str) sub.set_defaults(func=CLIAudio.translate, args_model=CLITranslationArgs) class CLITranscribeArgs(BaseModel): model: str file: str response_format: Optional[str] = None language: Optional[str] = None temperature: Optional[float] = None prompt: Optional[str] = None class CLITranslationArgs(BaseModel): model: str file: str response_format: Optional[str] = None language: Optional[str] = None temperature: Optional[float] = None prompt: Optional[str] = None class CLIAudio: @staticmethod def transcribe(args: CLITranscribeArgs) -> None: with open(args.file, "rb") as file_reader: buffer_reader = BufferReader(file_reader.read(), desc="Upload progress") model = cast( "Transcription | str", get_client().audio.transcriptions.create( file=(args.file, buffer_reader), model=args.model, language=args.language or omit, temperature=args.temperature or omit, prompt=args.prompt or omit, # casts required because the API is typed for enums # but we don't want to validate that here for forwards-compat response_format=cast(Any, args.response_format), ), ) if isinstance(model, str): sys.stdout.write(model + "\n") else: print_model(model) @staticmethod def translate(args: CLITranslationArgs) -> None: with open(args.file, "rb") as file_reader: buffer_reader = BufferReader(file_reader.read(), desc="Upload progress") model = cast( "Transcription | str", get_client().audio.translations.create( file=(args.file, buffer_reader), model=args.model, temperature=args.temperature or omit, prompt=args.prompt or omit, # casts required because the API is typed for enums # but we don't want to validate that here for forwards-compat response_format=cast(Any, args.response_format), ), ) if isinstance(model, str): sys.stdout.write(model + "\n") else: print_model(model) ================================================ FILE: src/openai/cli/_api/chat/__init__.py ================================================ from __future__ import annotations from typing import TYPE_CHECKING from argparse import ArgumentParser from . import completions if TYPE_CHECKING: from argparse import _SubParsersAction def register(subparser: _SubParsersAction[ArgumentParser]) -> None: completions.register(subparser) ================================================ FILE: src/openai/cli/_api/chat/completions.py ================================================ from __future__ import annotations import sys from typing import TYPE_CHECKING, List, Optional, cast from argparse import ArgumentParser from typing_extensions import Literal, NamedTuple from ..._utils import get_client from ..._models import BaseModel from ...._streaming import Stream from ....types.chat import ( ChatCompletionRole, ChatCompletionChunk, CompletionCreateParams, ) from ....types.chat.completion_create_params import ( CompletionCreateParamsStreaming, CompletionCreateParamsNonStreaming, ) if TYPE_CHECKING: from argparse import _SubParsersAction def register(subparser: _SubParsersAction[ArgumentParser]) -> None: sub = subparser.add_parser("chat.completions.create") sub._action_groups.pop() req = sub.add_argument_group("required arguments") opt = sub.add_argument_group("optional arguments") req.add_argument( "-g", "--message", action="append", nargs=2, metavar=("ROLE", "CONTENT"), help="A message in `{role} {content}` format. Use this argument multiple times to add multiple messages.", required=True, ) req.add_argument( "-m", "--model", help="The model to use.", required=True, ) opt.add_argument( "-n", "--n", help="How many completions to generate for the conversation.", type=int, ) opt.add_argument("-M", "--max-tokens", help="The maximum number of tokens to generate.", type=int) opt.add_argument( "-t", "--temperature", help="""What sampling temperature to use. Higher values means the model will take more risks. Try 0.9 for more creative applications, and 0 (argmax sampling) for ones with a well-defined answer. Mutually exclusive with `top_p`.""", type=float, ) opt.add_argument( "-P", "--top_p", help="""An alternative to sampling with temperature, called nucleus sampling, where the considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10%% probability mass are considered. Mutually exclusive with `temperature`.""", type=float, ) opt.add_argument( "--stop", help="A stop sequence at which to stop generating tokens for the message.", ) opt.add_argument("--stream", help="Stream messages as they're ready.", action="store_true") sub.set_defaults(func=CLIChatCompletion.create, args_model=CLIChatCompletionCreateArgs) class CLIMessage(NamedTuple): role: ChatCompletionRole content: str class CLIChatCompletionCreateArgs(BaseModel): message: List[CLIMessage] model: str n: Optional[int] = None max_tokens: Optional[int] = None temperature: Optional[float] = None top_p: Optional[float] = None stop: Optional[str] = None stream: bool = False class CLIChatCompletion: @staticmethod def create(args: CLIChatCompletionCreateArgs) -> None: params: CompletionCreateParams = { "model": args.model, "messages": [ {"role": cast(Literal["user"], message.role), "content": message.content} for message in args.message ], # type checkers are not good at inferring union types so we have to set stream afterwards "stream": False, } if args.temperature is not None: params["temperature"] = args.temperature if args.stop is not None: params["stop"] = args.stop if args.top_p is not None: params["top_p"] = args.top_p if args.n is not None: params["n"] = args.n if args.stream: params["stream"] = args.stream # type: ignore if args.max_tokens is not None: params["max_tokens"] = args.max_tokens if args.stream: return CLIChatCompletion._stream_create(cast(CompletionCreateParamsStreaming, params)) return CLIChatCompletion._create(cast(CompletionCreateParamsNonStreaming, params)) @staticmethod def _create(params: CompletionCreateParamsNonStreaming) -> None: completion = get_client().chat.completions.create(**params) should_print_header = len(completion.choices) > 1 for choice in completion.choices: if should_print_header: sys.stdout.write("===== Chat Completion {} =====\n".format(choice.index)) content = choice.message.content if choice.message.content is not None else "None" sys.stdout.write(content) if should_print_header or not content.endswith("\n"): sys.stdout.write("\n") sys.stdout.flush() @staticmethod def _stream_create(params: CompletionCreateParamsStreaming) -> None: # cast is required for mypy stream = cast( # pyright: ignore[reportUnnecessaryCast] Stream[ChatCompletionChunk], get_client().chat.completions.create(**params) ) for chunk in stream: should_print_header = len(chunk.choices) > 1 for choice in chunk.choices: if should_print_header: sys.stdout.write("===== Chat Completion {} =====\n".format(choice.index)) content = choice.delta.content or "" sys.stdout.write(content) if should_print_header: sys.stdout.write("\n") sys.stdout.flush() sys.stdout.write("\n") ================================================ FILE: src/openai/cli/_api/completions.py ================================================ from __future__ import annotations import sys from typing import TYPE_CHECKING, Optional, cast from argparse import ArgumentParser from functools import partial from openai.types.completion import Completion from .._utils import get_client from ..._types import Omittable, omit from ..._utils import is_given from .._errors import CLIError from .._models import BaseModel from ..._streaming import Stream if TYPE_CHECKING: from argparse import _SubParsersAction def register(subparser: _SubParsersAction[ArgumentParser]) -> None: sub = subparser.add_parser("completions.create") # Required sub.add_argument( "-m", "--model", help="The model to use", required=True, ) # Optional sub.add_argument("-p", "--prompt", help="An optional prompt to complete from") sub.add_argument("--stream", help="Stream tokens as they're ready.", action="store_true") sub.add_argument("-M", "--max-tokens", help="The maximum number of tokens to generate", type=int) sub.add_argument( "-t", "--temperature", help="""What sampling temperature to use. Higher values means the model will take more risks. Try 0.9 for more creative applications, and 0 (argmax sampling) for ones with a well-defined answer. Mutually exclusive with `top_p`.""", type=float, ) sub.add_argument( "-P", "--top_p", help="""An alternative to sampling with temperature, called nucleus sampling, where the considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10%% probability mass are considered. Mutually exclusive with `temperature`.""", type=float, ) sub.add_argument( "-n", "--n", help="How many sub-completions to generate for each prompt.", type=int, ) sub.add_argument( "--logprobs", help="Include the log probabilities on the `logprobs` most likely tokens, as well the chosen tokens. So for example, if `logprobs` is 10, the API will return a list of the 10 most likely tokens. If `logprobs` is 0, only the chosen tokens will have logprobs returned.", type=int, ) sub.add_argument( "--best_of", help="Generates `best_of` completions server-side and returns the 'best' (the one with the highest log probability per token). Results cannot be streamed.", type=int, ) sub.add_argument( "--echo", help="Echo back the prompt in addition to the completion", action="store_true", ) sub.add_argument( "--frequency_penalty", help="Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.", type=float, ) sub.add_argument( "--presence_penalty", help="Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.", type=float, ) sub.add_argument("--suffix", help="The suffix that comes after a completion of inserted text.") sub.add_argument("--stop", help="A stop sequence at which to stop generating tokens.") sub.add_argument( "--user", help="A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse.", ) # TODO: add support for logit_bias sub.set_defaults(func=CLICompletions.create, args_model=CLICompletionCreateArgs) class CLICompletionCreateArgs(BaseModel): model: str stream: bool = False prompt: Optional[str] = None n: Omittable[int] = omit stop: Omittable[str] = omit user: Omittable[str] = omit echo: Omittable[bool] = omit suffix: Omittable[str] = omit best_of: Omittable[int] = omit top_p: Omittable[float] = omit logprobs: Omittable[int] = omit max_tokens: Omittable[int] = omit temperature: Omittable[float] = omit presence_penalty: Omittable[float] = omit frequency_penalty: Omittable[float] = omit class CLICompletions: @staticmethod def create(args: CLICompletionCreateArgs) -> None: if is_given(args.n) and args.n > 1 and args.stream: raise CLIError("Can't stream completions with n>1 with the current CLI") make_request = partial( get_client().completions.create, n=args.n, echo=args.echo, stop=args.stop, user=args.user, model=args.model, top_p=args.top_p, prompt=args.prompt, suffix=args.suffix, best_of=args.best_of, logprobs=args.logprobs, max_tokens=args.max_tokens, temperature=args.temperature, presence_penalty=args.presence_penalty, frequency_penalty=args.frequency_penalty, ) if args.stream: return CLICompletions._stream_create( # mypy doesn't understand the `partial` function but pyright does cast(Stream[Completion], make_request(stream=True)) # pyright: ignore[reportUnnecessaryCast] ) return CLICompletions._create(make_request()) @staticmethod def _create(completion: Completion) -> None: should_print_header = len(completion.choices) > 1 for choice in completion.choices: if should_print_header: sys.stdout.write("===== Completion {} =====\n".format(choice.index)) sys.stdout.write(choice.text) if should_print_header or not choice.text.endswith("\n"): sys.stdout.write("\n") sys.stdout.flush() @staticmethod def _stream_create(stream: Stream[Completion]) -> None: for completion in stream: should_print_header = len(completion.choices) > 1 for choice in sorted(completion.choices, key=lambda c: c.index): if should_print_header: sys.stdout.write("===== Chat Completion {} =====\n".format(choice.index)) sys.stdout.write(choice.text) if should_print_header: sys.stdout.write("\n") sys.stdout.flush() sys.stdout.write("\n") ================================================ FILE: src/openai/cli/_api/files.py ================================================ from __future__ import annotations from typing import TYPE_CHECKING, Any, cast from argparse import ArgumentParser from .._utils import get_client, print_model from .._models import BaseModel from .._progress import BufferReader if TYPE_CHECKING: from argparse import _SubParsersAction def register(subparser: _SubParsersAction[ArgumentParser]) -> None: sub = subparser.add_parser("files.create") sub.add_argument( "-f", "--file", required=True, help="File to upload", ) sub.add_argument( "-p", "--purpose", help="Why are you uploading this file? (see https://platform.openai.com/docs/api-reference/ for purposes)", required=True, ) sub.set_defaults(func=CLIFile.create, args_model=CLIFileCreateArgs) sub = subparser.add_parser("files.retrieve") sub.add_argument("-i", "--id", required=True, help="The files ID") sub.set_defaults(func=CLIFile.get, args_model=CLIFileCreateArgs) sub = subparser.add_parser("files.delete") sub.add_argument("-i", "--id", required=True, help="The files ID") sub.set_defaults(func=CLIFile.delete, args_model=CLIFileCreateArgs) sub = subparser.add_parser("files.list") sub.set_defaults(func=CLIFile.list) class CLIFileIDArgs(BaseModel): id: str class CLIFileCreateArgs(BaseModel): file: str purpose: str class CLIFile: @staticmethod def create(args: CLIFileCreateArgs) -> None: with open(args.file, "rb") as file_reader: buffer_reader = BufferReader(file_reader.read(), desc="Upload progress") file = get_client().files.create( file=(args.file, buffer_reader), # casts required because the API is typed for enums # but we don't want to validate that here for forwards-compat purpose=cast(Any, args.purpose), ) print_model(file) @staticmethod def get(args: CLIFileIDArgs) -> None: file = get_client().files.retrieve(file_id=args.id) print_model(file) @staticmethod def delete(args: CLIFileIDArgs) -> None: file = get_client().files.delete(file_id=args.id) print_model(file) @staticmethod def list() -> None: files = get_client().files.list() for file in files: print_model(file) ================================================ FILE: src/openai/cli/_api/fine_tuning/__init__.py ================================================ from __future__ import annotations from typing import TYPE_CHECKING from argparse import ArgumentParser from . import jobs if TYPE_CHECKING: from argparse import _SubParsersAction def register(subparser: _SubParsersAction[ArgumentParser]) -> None: jobs.register(subparser) ================================================ FILE: src/openai/cli/_api/fine_tuning/jobs.py ================================================ from __future__ import annotations import json from typing import TYPE_CHECKING from argparse import ArgumentParser from ..._utils import get_client, print_model from ...._types import Omittable, omit from ...._utils import is_given from ..._models import BaseModel from ....pagination import SyncCursorPage from ....types.fine_tuning import ( FineTuningJob, FineTuningJobEvent, ) if TYPE_CHECKING: from argparse import _SubParsersAction def register(subparser: _SubParsersAction[ArgumentParser]) -> None: sub = subparser.add_parser("fine_tuning.jobs.create") sub.add_argument( "-m", "--model", help="The model to fine-tune.", required=True, ) sub.add_argument( "-F", "--training-file", help="The training file to fine-tune the model on.", required=True, ) sub.add_argument( "-H", "--hyperparameters", help="JSON string of hyperparameters to use for fine-tuning.", type=str, ) sub.add_argument( "-s", "--suffix", help="A suffix to add to the fine-tuned model name.", ) sub.add_argument( "-V", "--validation-file", help="The validation file to use for fine-tuning.", ) sub.set_defaults(func=CLIFineTuningJobs.create, args_model=CLIFineTuningJobsCreateArgs) sub = subparser.add_parser("fine_tuning.jobs.retrieve") sub.add_argument( "-i", "--id", help="The ID of the fine-tuning job to retrieve.", required=True, ) sub.set_defaults(func=CLIFineTuningJobs.retrieve, args_model=CLIFineTuningJobsRetrieveArgs) sub = subparser.add_parser("fine_tuning.jobs.list") sub.add_argument( "-a", "--after", help="Identifier for the last job from the previous pagination request. If provided, only jobs created after this job will be returned.", ) sub.add_argument( "-l", "--limit", help="Number of fine-tuning jobs to retrieve.", type=int, ) sub.set_defaults(func=CLIFineTuningJobs.list, args_model=CLIFineTuningJobsListArgs) sub = subparser.add_parser("fine_tuning.jobs.cancel") sub.add_argument( "-i", "--id", help="The ID of the fine-tuning job to cancel.", required=True, ) sub.set_defaults(func=CLIFineTuningJobs.cancel, args_model=CLIFineTuningJobsCancelArgs) sub = subparser.add_parser("fine_tuning.jobs.list_events") sub.add_argument( "-i", "--id", help="The ID of the fine-tuning job to list events for.", required=True, ) sub.add_argument( "-a", "--after", help="Identifier for the last event from the previous pagination request. If provided, only events created after this event will be returned.", ) sub.add_argument( "-l", "--limit", help="Number of fine-tuning job events to retrieve.", type=int, ) sub.set_defaults(func=CLIFineTuningJobs.list_events, args_model=CLIFineTuningJobsListEventsArgs) class CLIFineTuningJobsCreateArgs(BaseModel): model: str training_file: str hyperparameters: Omittable[str] = omit suffix: Omittable[str] = omit validation_file: Omittable[str] = omit class CLIFineTuningJobsRetrieveArgs(BaseModel): id: str class CLIFineTuningJobsListArgs(BaseModel): after: Omittable[str] = omit limit: Omittable[int] = omit class CLIFineTuningJobsCancelArgs(BaseModel): id: str class CLIFineTuningJobsListEventsArgs(BaseModel): id: str after: Omittable[str] = omit limit: Omittable[int] = omit class CLIFineTuningJobs: @staticmethod def create(args: CLIFineTuningJobsCreateArgs) -> None: hyperparameters = json.loads(str(args.hyperparameters)) if is_given(args.hyperparameters) else omit fine_tuning_job: FineTuningJob = get_client().fine_tuning.jobs.create( model=args.model, training_file=args.training_file, hyperparameters=hyperparameters, suffix=args.suffix, validation_file=args.validation_file, ) print_model(fine_tuning_job) @staticmethod def retrieve(args: CLIFineTuningJobsRetrieveArgs) -> None: fine_tuning_job: FineTuningJob = get_client().fine_tuning.jobs.retrieve(fine_tuning_job_id=args.id) print_model(fine_tuning_job) @staticmethod def list(args: CLIFineTuningJobsListArgs) -> None: fine_tuning_jobs: SyncCursorPage[FineTuningJob] = get_client().fine_tuning.jobs.list( after=args.after or omit, limit=args.limit or omit ) print_model(fine_tuning_jobs) @staticmethod def cancel(args: CLIFineTuningJobsCancelArgs) -> None: fine_tuning_job: FineTuningJob = get_client().fine_tuning.jobs.cancel(fine_tuning_job_id=args.id) print_model(fine_tuning_job) @staticmethod def list_events(args: CLIFineTuningJobsListEventsArgs) -> None: fine_tuning_job_events: SyncCursorPage[FineTuningJobEvent] = get_client().fine_tuning.jobs.list_events( fine_tuning_job_id=args.id, after=args.after or omit, limit=args.limit or omit, ) print_model(fine_tuning_job_events) ================================================ FILE: src/openai/cli/_api/image.py ================================================ from __future__ import annotations from typing import TYPE_CHECKING, Any, cast from argparse import ArgumentParser from .._utils import get_client, print_model from ..._types import Omit, Omittable, omit from .._models import BaseModel from .._progress import BufferReader if TYPE_CHECKING: from argparse import _SubParsersAction def register(subparser: _SubParsersAction[ArgumentParser]) -> None: sub = subparser.add_parser("images.generate") sub.add_argument("-m", "--model", type=str) sub.add_argument("-p", "--prompt", type=str, required=True) sub.add_argument("-n", "--num-images", type=int, default=1) sub.add_argument("-s", "--size", type=str, default="1024x1024", help="Size of the output image") sub.add_argument("--response-format", type=str, default="url") sub.set_defaults(func=CLIImage.create, args_model=CLIImageCreateArgs) sub = subparser.add_parser("images.edit") sub.add_argument("-m", "--model", type=str) sub.add_argument("-p", "--prompt", type=str, required=True) sub.add_argument("-n", "--num-images", type=int, default=1) sub.add_argument( "-I", "--image", type=str, required=True, help="Image to modify. Should be a local path and a PNG encoded image.", ) sub.add_argument("-s", "--size", type=str, default="1024x1024", help="Size of the output image") sub.add_argument("--response-format", type=str, default="url") sub.add_argument( "-M", "--mask", type=str, required=False, help="Path to a mask image. It should be the same size as the image you're editing and a RGBA PNG image. The Alpha channel acts as the mask.", ) sub.set_defaults(func=CLIImage.edit, args_model=CLIImageEditArgs) sub = subparser.add_parser("images.create_variation") sub.add_argument("-m", "--model", type=str) sub.add_argument("-n", "--num-images", type=int, default=1) sub.add_argument( "-I", "--image", type=str, required=True, help="Image to modify. Should be a local path and a PNG encoded image.", ) sub.add_argument("-s", "--size", type=str, default="1024x1024", help="Size of the output image") sub.add_argument("--response-format", type=str, default="url") sub.set_defaults(func=CLIImage.create_variation, args_model=CLIImageCreateVariationArgs) class CLIImageCreateArgs(BaseModel): prompt: str num_images: int size: str response_format: str model: Omittable[str] = omit class CLIImageCreateVariationArgs(BaseModel): image: str num_images: int size: str response_format: str model: Omittable[str] = omit class CLIImageEditArgs(BaseModel): image: str num_images: int size: str response_format: str prompt: str mask: Omittable[str] = omit model: Omittable[str] = omit class CLIImage: @staticmethod def create(args: CLIImageCreateArgs) -> None: image = get_client().images.generate( model=args.model, prompt=args.prompt, n=args.num_images, # casts required because the API is typed for enums # but we don't want to validate that here for forwards-compat size=cast(Any, args.size), response_format=cast(Any, args.response_format), ) print_model(image) @staticmethod def create_variation(args: CLIImageCreateVariationArgs) -> None: with open(args.image, "rb") as file_reader: buffer_reader = BufferReader(file_reader.read(), desc="Upload progress") image = get_client().images.create_variation( model=args.model, image=("image", buffer_reader), n=args.num_images, # casts required because the API is typed for enums # but we don't want to validate that here for forwards-compat size=cast(Any, args.size), response_format=cast(Any, args.response_format), ) print_model(image) @staticmethod def edit(args: CLIImageEditArgs) -> None: with open(args.image, "rb") as file_reader: buffer_reader = BufferReader(file_reader.read(), desc="Image upload progress") if isinstance(args.mask, Omit): mask: Omittable[BufferReader] = omit else: with open(args.mask, "rb") as file_reader: mask = BufferReader(file_reader.read(), desc="Mask progress") image = get_client().images.edit( model=args.model, prompt=args.prompt, image=("image", buffer_reader), n=args.num_images, mask=("mask", mask) if not isinstance(mask, Omit) else mask, # casts required because the API is typed for enums # but we don't want to validate that here for forwards-compat size=cast(Any, args.size), response_format=cast(Any, args.response_format), ) print_model(image) ================================================ FILE: src/openai/cli/_api/models.py ================================================ from __future__ import annotations from typing import TYPE_CHECKING from argparse import ArgumentParser from .._utils import get_client, print_model from .._models import BaseModel if TYPE_CHECKING: from argparse import _SubParsersAction def register(subparser: _SubParsersAction[ArgumentParser]) -> None: sub = subparser.add_parser("models.list") sub.set_defaults(func=CLIModels.list) sub = subparser.add_parser("models.retrieve") sub.add_argument("-i", "--id", required=True, help="The model ID") sub.set_defaults(func=CLIModels.get, args_model=CLIModelIDArgs) sub = subparser.add_parser("models.delete") sub.add_argument("-i", "--id", required=True, help="The model ID") sub.set_defaults(func=CLIModels.delete, args_model=CLIModelIDArgs) class CLIModelIDArgs(BaseModel): id: str class CLIModels: @staticmethod def get(args: CLIModelIDArgs) -> None: model = get_client().models.retrieve(model=args.id) print_model(model) @staticmethod def delete(args: CLIModelIDArgs) -> None: model = get_client().models.delete(model=args.id) print_model(model) @staticmethod def list() -> None: models = get_client().models.list() for model in models: print_model(model) ================================================ FILE: src/openai/cli/_cli.py ================================================ from __future__ import annotations import sys import logging import argparse from typing import Any, List, Type, Optional from typing_extensions import ClassVar import httpx import pydantic import openai from . import _tools from .. import _ApiType, __version__ from ._api import register_commands from ._utils import can_use_http2 from ._errors import CLIError, display_error from .._compat import PYDANTIC_V1, ConfigDict, model_parse from .._models import BaseModel from .._exceptions import APIError logger = logging.getLogger() formatter = logging.Formatter("[%(asctime)s] %(message)s") handler = logging.StreamHandler(sys.stderr) handler.setFormatter(formatter) logger.addHandler(handler) class Arguments(BaseModel): if PYDANTIC_V1: class Config(pydantic.BaseConfig): # type: ignore extra: Any = pydantic.Extra.ignore # type: ignore else: model_config: ClassVar[ConfigDict] = ConfigDict( extra="ignore", ) verbosity: int version: Optional[str] = None api_key: Optional[str] api_base: Optional[str] organization: Optional[str] proxy: Optional[List[str]] api_type: Optional[_ApiType] = None api_version: Optional[str] = None # azure azure_endpoint: Optional[str] = None azure_ad_token: Optional[str] = None # internal, set by subparsers to parse their specific args args_model: Optional[Type[BaseModel]] = None # internal, used so that subparsers can forward unknown arguments unknown_args: List[str] = [] allow_unknown_args: bool = False def _build_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser(description=None, prog="openai") parser.add_argument( "-v", "--verbose", action="count", dest="verbosity", default=0, help="Set verbosity.", ) parser.add_argument("-b", "--api-base", help="What API base url to use.") parser.add_argument("-k", "--api-key", help="What API key to use.") parser.add_argument("-p", "--proxy", nargs="+", help="What proxy to use.") parser.add_argument( "-o", "--organization", help="Which organization to run as (will use your default organization if not specified)", ) parser.add_argument( "-t", "--api-type", type=str, choices=("openai", "azure"), help="The backend API to call, must be `openai` or `azure`", ) parser.add_argument( "--api-version", help="The Azure API version, e.g. 'https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#rest-api-versioning'", ) # azure parser.add_argument( "--azure-endpoint", help="The Azure endpoint, e.g. 'https://endpoint.openai.azure.com'", ) parser.add_argument( "--azure-ad-token", help="A token from Azure Active Directory, https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-id", ) # prints the package version parser.add_argument( "-V", "--version", action="version", version="%(prog)s " + __version__, ) def help() -> None: parser.print_help() parser.set_defaults(func=help) subparsers = parser.add_subparsers() sub_api = subparsers.add_parser("api", help="Direct API calls") register_commands(sub_api) sub_tools = subparsers.add_parser("tools", help="Client side tools for convenience") _tools.register_commands(sub_tools, subparsers) return parser def main() -> int: try: _main() except (APIError, CLIError, pydantic.ValidationError) as err: display_error(err) return 1 except KeyboardInterrupt: sys.stderr.write("\n") return 1 return 0 def _parse_args(parser: argparse.ArgumentParser) -> tuple[argparse.Namespace, Arguments, list[str]]: # argparse by default will strip out the `--` but we want to keep it for unknown arguments if "--" in sys.argv: idx = sys.argv.index("--") known_args = sys.argv[1:idx] unknown_args = sys.argv[idx:] else: known_args = sys.argv[1:] unknown_args = [] parsed, remaining_unknown = parser.parse_known_args(known_args) # append any remaining unknown arguments from the initial parsing remaining_unknown.extend(unknown_args) args = model_parse(Arguments, vars(parsed)) if not args.allow_unknown_args: # we have to parse twice to ensure any unknown arguments # result in an error if that behaviour is desired parser.parse_args() return parsed, args, remaining_unknown def _main() -> None: parser = _build_parser() parsed, args, unknown = _parse_args(parser) if args.verbosity != 0: sys.stderr.write("Warning: --verbosity isn't supported yet\n") proxies: dict[str, httpx.BaseTransport] = {} if args.proxy is not None: for proxy in args.proxy: key = "https://" if proxy.startswith("https") else "http://" if key in proxies: raise CLIError(f"Multiple {key} proxies given - only the last one would be used") proxies[key] = httpx.HTTPTransport(proxy=httpx.Proxy(httpx.URL(proxy))) http_client = httpx.Client( mounts=proxies or None, http2=can_use_http2(), ) openai.http_client = http_client if args.organization: openai.organization = args.organization if args.api_key: openai.api_key = args.api_key if args.api_base: openai.base_url = args.api_base # azure if args.api_type is not None: openai.api_type = args.api_type if args.azure_endpoint is not None: openai.azure_endpoint = args.azure_endpoint if args.api_version is not None: openai.api_version = args.api_version if args.azure_ad_token is not None: openai.azure_ad_token = args.azure_ad_token try: if args.args_model: parsed.func( model_parse( args.args_model, { **{ # we omit None values so that they can be defaulted to `NotGiven` # and we'll strip it from the API request key: value for key, value in vars(parsed).items() if value is not None }, "unknown_args": unknown, }, ) ) else: parsed.func() finally: try: http_client.close() except Exception: pass if __name__ == "__main__": sys.exit(main()) ================================================ FILE: src/openai/cli/_errors.py ================================================ from __future__ import annotations import sys import pydantic from ._utils import Colors, organization_info from .._exceptions import APIError, OpenAIError class CLIError(OpenAIError): ... class SilentCLIError(CLIError): ... def display_error(err: CLIError | APIError | pydantic.ValidationError) -> None: if isinstance(err, SilentCLIError): return sys.stderr.write("{}{}Error:{} {}\n".format(organization_info(), Colors.FAIL, Colors.ENDC, err)) ================================================ FILE: src/openai/cli/_models.py ================================================ from typing import Any from typing_extensions import ClassVar import pydantic from .. import _models from .._compat import PYDANTIC_V1, ConfigDict class BaseModel(_models.BaseModel): if PYDANTIC_V1: class Config(pydantic.BaseConfig): # type: ignore extra: Any = pydantic.Extra.ignore # type: ignore arbitrary_types_allowed: bool = True else: model_config: ClassVar[ConfigDict] = ConfigDict(extra="ignore", arbitrary_types_allowed=True) ================================================ FILE: src/openai/cli/_progress.py ================================================ from __future__ import annotations import io from typing import Callable from typing_extensions import override class CancelledError(Exception): def __init__(self, msg: str) -> None: self.msg = msg super().__init__(msg) @override def __str__(self) -> str: return self.msg __repr__ = __str__ class BufferReader(io.BytesIO): def __init__(self, buf: bytes = b"", desc: str | None = None) -> None: super().__init__(buf) self._len = len(buf) self._progress = 0 self._callback = progress(len(buf), desc=desc) def __len__(self) -> int: return self._len @override def read(self, n: int | None = -1) -> bytes: chunk = io.BytesIO.read(self, n) self._progress += len(chunk) try: self._callback(self._progress) except Exception as e: # catches exception from the callback raise CancelledError("The upload was cancelled: {}".format(e)) from e return chunk def progress(total: float, desc: str | None) -> Callable[[float], None]: import tqdm meter = tqdm.tqdm(total=total, unit_scale=True, desc=desc) def incr(progress: float) -> None: meter.n = progress if progress == total: meter.close() else: meter.refresh() return incr def MB(i: int) -> int: return int(i // 1024**2) ================================================ FILE: src/openai/cli/_tools/__init__.py ================================================ from ._main import register_commands as register_commands ================================================ FILE: src/openai/cli/_tools/_main.py ================================================ from __future__ import annotations from typing import TYPE_CHECKING from argparse import ArgumentParser from . import migrate, fine_tunes if TYPE_CHECKING: from argparse import _SubParsersAction def register_commands(parser: ArgumentParser, subparser: _SubParsersAction[ArgumentParser]) -> None: migrate.register(subparser) namespaced = parser.add_subparsers(title="Tools", help="Convenience client side tools") fine_tunes.register(namespaced) ================================================ FILE: src/openai/cli/_tools/fine_tunes.py ================================================ from __future__ import annotations import sys from typing import TYPE_CHECKING from argparse import ArgumentParser from .._models import BaseModel from ...lib._validators import ( get_validators, write_out_file, read_any_format, apply_validators, apply_necessary_remediation, ) if TYPE_CHECKING: from argparse import _SubParsersAction def register(subparser: _SubParsersAction[ArgumentParser]) -> None: sub = subparser.add_parser("fine_tunes.prepare_data") sub.add_argument( "-f", "--file", required=True, help="JSONL, JSON, CSV, TSV, TXT or XLSX file containing prompt-completion examples to be analyzed." "This should be the local file path.", ) sub.add_argument( "-q", "--quiet", required=False, action="store_true", help="Auto accepts all suggestions, without asking for user input. To be used within scripts.", ) sub.set_defaults(func=prepare_data, args_model=PrepareDataArgs) class PrepareDataArgs(BaseModel): file: str quiet: bool def prepare_data(args: PrepareDataArgs) -> None: sys.stdout.write("Analyzing...\n") fname = args.file auto_accept = args.quiet df, remediation = read_any_format(fname) apply_necessary_remediation(None, remediation) validators = get_validators() assert df is not None apply_validators( df, fname, remediation, validators, auto_accept, write_out_file_func=write_out_file, ) ================================================ FILE: src/openai/cli/_tools/migrate.py ================================================ from __future__ import annotations import os import sys import shutil import tarfile import platform import subprocess from typing import TYPE_CHECKING, List from pathlib import Path from argparse import ArgumentParser import httpx from .._errors import CLIError, SilentCLIError from .._models import BaseModel if TYPE_CHECKING: from argparse import _SubParsersAction def register(subparser: _SubParsersAction[ArgumentParser]) -> None: sub = subparser.add_parser("migrate") sub.set_defaults(func=migrate, args_model=MigrateArgs, allow_unknown_args=True) sub = subparser.add_parser("grit") sub.set_defaults(func=grit, args_model=GritArgs, allow_unknown_args=True) class GritArgs(BaseModel): # internal unknown_args: List[str] = [] def grit(args: GritArgs) -> None: grit_path = install() try: subprocess.check_call([grit_path, *args.unknown_args]) except subprocess.CalledProcessError: # stdout and stderr are forwarded by subprocess so an error will already # have been displayed raise SilentCLIError() from None class MigrateArgs(BaseModel): # internal unknown_args: List[str] = [] def migrate(args: MigrateArgs) -> None: grit_path = install() try: subprocess.check_call([grit_path, "apply", "openai", *args.unknown_args]) except subprocess.CalledProcessError: # stdout and stderr are forwarded by subprocess so an error will already # have been displayed raise SilentCLIError() from None # handles downloading the Grit CLI until they provide their own PyPi package KEYGEN_ACCOUNT = "custodian-dev" def _cache_dir() -> Path: xdg = os.environ.get("XDG_CACHE_HOME") if xdg is not None: return Path(xdg) return Path.home() / ".cache" def _debug(message: str) -> None: if not os.environ.get("DEBUG"): return sys.stdout.write(f"[DEBUG]: {message}\n") def install() -> Path: """Installs the Grit CLI and returns the location of the binary""" if sys.platform == "win32": raise CLIError("Windows is not supported yet in the migration CLI") _debug("Using Grit installer from GitHub") platform = "apple-darwin" if sys.platform == "darwin" else "unknown-linux-gnu" dir_name = _cache_dir() / "openai-python" install_dir = dir_name / ".install" target_dir = install_dir / "bin" target_path = target_dir / "grit" temp_file = target_dir / "grit.tmp" if target_path.exists(): _debug(f"{target_path} already exists") sys.stdout.flush() return target_path _debug(f"Using Grit CLI path: {target_path}") target_dir.mkdir(parents=True, exist_ok=True) if temp_file.exists(): temp_file.unlink() arch = _get_arch() _debug(f"Using architecture {arch}") file_name = f"grit-{arch}-{platform}" download_url = f"https://github.com/getgrit/gritql/releases/latest/download/{file_name}.tar.gz" sys.stdout.write(f"Downloading Grit CLI from {download_url}\n") with httpx.Client() as client: download_response = client.get(download_url, follow_redirects=True) if download_response.status_code != 200: raise CLIError(f"Failed to download Grit CLI from {download_url}") with open(temp_file, "wb") as file: for chunk in download_response.iter_bytes(): file.write(chunk) unpacked_dir = target_dir / "cli-bin" unpacked_dir.mkdir(parents=True, exist_ok=True) with tarfile.open(temp_file, "r:gz") as archive: if sys.version_info >= (3, 12): archive.extractall(unpacked_dir, filter="data") else: archive.extractall(unpacked_dir) _move_files_recursively(unpacked_dir, target_dir) shutil.rmtree(unpacked_dir) os.remove(temp_file) os.chmod(target_path, 0o755) sys.stdout.flush() return target_path def _move_files_recursively(source_dir: Path, target_dir: Path) -> None: for item in source_dir.iterdir(): if item.is_file(): item.rename(target_dir / item.name) elif item.is_dir(): _move_files_recursively(item, target_dir) def _get_arch() -> str: architecture = platform.machine().lower() # Map the architecture names to Grit equivalents arch_map = { "x86_64": "x86_64", "amd64": "x86_64", "armv7l": "aarch64", "arm64": "aarch64", } return arch_map.get(architecture, architecture) ================================================ FILE: src/openai/cli/_utils.py ================================================ from __future__ import annotations import sys import openai from .. import OpenAI, _load_client from .._compat import model_json from .._models import BaseModel class Colors: HEADER = "\033[95m" OKBLUE = "\033[94m" OKGREEN = "\033[92m" WARNING = "\033[93m" FAIL = "\033[91m" ENDC = "\033[0m" BOLD = "\033[1m" UNDERLINE = "\033[4m" def get_client() -> OpenAI: return _load_client() def organization_info() -> str: organization = openai.organization if organization is not None: return "[organization={}] ".format(organization) return "" def print_model(model: BaseModel) -> None: sys.stdout.write(model_json(model, indent=2) + "\n") def can_use_http2() -> bool: try: import h2 # type: ignore # noqa except ImportError: return False return True ================================================ FILE: src/openai/helpers/__init__.py ================================================ from .microphone import Microphone from .local_audio_player import LocalAudioPlayer __all__ = ["Microphone", "LocalAudioPlayer"] ================================================ FILE: src/openai/helpers/local_audio_player.py ================================================ # mypy: ignore-errors from __future__ import annotations import queue import asyncio from typing import Any, Union, Callable, AsyncGenerator, cast from typing_extensions import TYPE_CHECKING from .. import _legacy_response from .._extras import numpy as np, sounddevice as sd from .._response import StreamedBinaryAPIResponse, AsyncStreamedBinaryAPIResponse if TYPE_CHECKING: import numpy.typing as npt SAMPLE_RATE = 24000 class LocalAudioPlayer: def __init__( self, should_stop: Union[Callable[[], bool], None] = None, ): self.channels = 1 self.dtype = np.float32 self.should_stop = should_stop async def _tts_response_to_buffer( self, response: Union[ _legacy_response.HttpxBinaryResponseContent, AsyncStreamedBinaryAPIResponse, StreamedBinaryAPIResponse, ], ) -> npt.NDArray[np.float32]: chunks: list[bytes] = [] if isinstance(response, _legacy_response.HttpxBinaryResponseContent) or isinstance( response, StreamedBinaryAPIResponse ): for chunk in response.iter_bytes(chunk_size=1024): if chunk: chunks.append(chunk) else: async for chunk in response.iter_bytes(chunk_size=1024): if chunk: chunks.append(chunk) audio_bytes = b"".join(chunks) audio_np = np.frombuffer(audio_bytes, dtype=np.int16).astype(np.float32) / 32767.0 audio_np = audio_np.reshape(-1, 1) return audio_np async def play( self, input: Union[ npt.NDArray[np.int16], npt.NDArray[np.float32], _legacy_response.HttpxBinaryResponseContent, AsyncStreamedBinaryAPIResponse, StreamedBinaryAPIResponse, ], ) -> None: audio_content: npt.NDArray[np.float32] if isinstance(input, np.ndarray): if input.dtype == np.int16 and self.dtype == np.float32: audio_content = (input.astype(np.float32) / 32767.0).reshape(-1, self.channels) elif input.dtype == np.float32: audio_content = cast("npt.NDArray[np.float32]", input) else: raise ValueError(f"Unsupported dtype: {input.dtype}") else: audio_content = await self._tts_response_to_buffer(input) loop = asyncio.get_event_loop() event = asyncio.Event() idx = 0 def callback( outdata: npt.NDArray[np.float32], frame_count: int, _time_info: Any, _status: Any, ): nonlocal idx remainder = len(audio_content) - idx if remainder == 0 or (callable(self.should_stop) and self.should_stop()): loop.call_soon_threadsafe(event.set) raise sd.CallbackStop valid_frames = frame_count if remainder >= frame_count else remainder outdata[:valid_frames] = audio_content[idx : idx + valid_frames] outdata[valid_frames:] = 0 idx += valid_frames stream = sd.OutputStream( samplerate=SAMPLE_RATE, callback=callback, dtype=audio_content.dtype, channels=audio_content.shape[1], ) with stream: await event.wait() async def play_stream( self, buffer_stream: AsyncGenerator[Union[npt.NDArray[np.float32], npt.NDArray[np.int16], None], None], ) -> None: loop = asyncio.get_event_loop() event = asyncio.Event() buffer_queue: queue.Queue[Union[npt.NDArray[np.float32], npt.NDArray[np.int16], None]] = queue.Queue(maxsize=50) async def buffer_producer(): async for buffer in buffer_stream: if buffer is None: break await loop.run_in_executor(None, buffer_queue.put, buffer) await loop.run_in_executor(None, buffer_queue.put, None) # Signal completion def callback( outdata: npt.NDArray[np.float32], frame_count: int, _time_info: Any, _status: Any, ): nonlocal current_buffer, buffer_pos frames_written = 0 while frames_written < frame_count: if current_buffer is None or buffer_pos >= len(current_buffer): try: current_buffer = buffer_queue.get(timeout=0.1) if current_buffer is None: loop.call_soon_threadsafe(event.set) raise sd.CallbackStop buffer_pos = 0 if current_buffer.dtype == np.int16 and self.dtype == np.float32: current_buffer = (current_buffer.astype(np.float32) / 32767.0).reshape(-1, self.channels) except queue.Empty: outdata[frames_written:] = 0 return remaining_frames = len(current_buffer) - buffer_pos frames_to_write = min(frame_count - frames_written, remaining_frames) outdata[frames_written : frames_written + frames_to_write] = current_buffer[ buffer_pos : buffer_pos + frames_to_write ] buffer_pos += frames_to_write frames_written += frames_to_write current_buffer = None buffer_pos = 0 producer_task = asyncio.create_task(buffer_producer()) with sd.OutputStream( samplerate=SAMPLE_RATE, channels=self.channels, dtype=self.dtype, callback=callback, ): await event.wait() await producer_task ================================================ FILE: src/openai/helpers/microphone.py ================================================ # mypy: ignore-errors from __future__ import annotations import io import time import wave import asyncio from typing import Any, Type, Union, Generic, TypeVar, Callable, overload from typing_extensions import TYPE_CHECKING, Literal from .._types import FileTypes, FileContent from .._extras import numpy as np, sounddevice as sd if TYPE_CHECKING: import numpy.typing as npt SAMPLE_RATE = 24000 DType = TypeVar("DType", bound=np.generic) class Microphone(Generic[DType]): def __init__( self, channels: int = 1, dtype: Type[DType] = np.int16, should_record: Union[Callable[[], bool], None] = None, timeout: Union[float, None] = None, ): self.channels = channels self.dtype = dtype self.should_record = should_record self.buffer_chunks = [] self.timeout = timeout self.has_record_function = callable(should_record) def _ndarray_to_wav(self, audio_data: npt.NDArray[DType]) -> FileTypes: buffer: FileContent = io.BytesIO() with wave.open(buffer, "w") as wav_file: wav_file.setnchannels(self.channels) wav_file.setsampwidth(np.dtype(self.dtype).itemsize) wav_file.setframerate(SAMPLE_RATE) wav_file.writeframes(audio_data.tobytes()) buffer.seek(0) return ("audio.wav", buffer, "audio/wav") @overload async def record(self, return_ndarray: Literal[True]) -> npt.NDArray[DType]: ... @overload async def record(self, return_ndarray: Literal[False]) -> FileTypes: ... @overload async def record(self, return_ndarray: None = ...) -> FileTypes: ... async def record(self, return_ndarray: Union[bool, None] = False) -> Union[npt.NDArray[DType], FileTypes]: loop = asyncio.get_event_loop() event = asyncio.Event() self.buffer_chunks: list[npt.NDArray[DType]] = [] start_time = time.perf_counter() def callback( indata: npt.NDArray[DType], _frame_count: int, _time_info: Any, _status: Any, ): execution_time = time.perf_counter() - start_time reached_recording_timeout = execution_time > self.timeout if self.timeout is not None else False if reached_recording_timeout: loop.call_soon_threadsafe(event.set) raise sd.CallbackStop should_be_recording = self.should_record() if callable(self.should_record) else True if not should_be_recording: loop.call_soon_threadsafe(event.set) raise sd.CallbackStop self.buffer_chunks.append(indata.copy()) stream = sd.InputStream( callback=callback, dtype=self.dtype, samplerate=SAMPLE_RATE, channels=self.channels, ) with stream: await event.wait() # Concatenate all chunks into a single buffer, handle empty case concatenated_chunks: npt.NDArray[DType] = ( np.concatenate(self.buffer_chunks, axis=0) if len(self.buffer_chunks) > 0 else np.array([], dtype=self.dtype) ) if return_ndarray: return concatenated_chunks else: return self._ndarray_to_wav(concatenated_chunks) ================================================ FILE: src/openai/lib/.keep ================================================ File generated from our OpenAPI spec by Stainless. This directory can be used to store custom files to expand the SDK. It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. ================================================ FILE: src/openai/lib/__init__.py ================================================ from ._tools import pydantic_function_tool as pydantic_function_tool from ._parsing import ResponseFormatT as ResponseFormatT ================================================ FILE: src/openai/lib/_old_api.py ================================================ from __future__ import annotations from typing import TYPE_CHECKING, Any from typing_extensions import override from .._utils import LazyProxy from .._exceptions import OpenAIError INSTRUCTIONS = """ You tried to access openai.{symbol}, but this is no longer supported in openai>=1.0.0 - see the README at https://github.com/openai/openai-python for the API. You can run `openai migrate` to automatically upgrade your codebase to use the 1.0.0 interface. Alternatively, you can pin your installation to the old version, e.g. `pip install openai==0.28` A detailed migration guide is available here: https://github.com/openai/openai-python/discussions/742 """ class APIRemovedInV1(OpenAIError): def __init__(self, *, symbol: str) -> None: super().__init__(INSTRUCTIONS.format(symbol=symbol)) class APIRemovedInV1Proxy(LazyProxy[Any]): def __init__(self, *, symbol: str) -> None: super().__init__() self._symbol = symbol @override def __load__(self) -> Any: # return the proxy until it is eventually called so that # we don't break people that are just checking the attributes # of a module return self def __call__(self, *_args: Any, **_kwargs: Any) -> Any: raise APIRemovedInV1(symbol=self._symbol) SYMBOLS = [ "Edit", "File", "Audio", "Image", "Model", "Engine", "Customer", "FineTune", "Embedding", "Completion", "Deployment", "Moderation", "ErrorObject", "FineTuningJob", "ChatCompletion", ] # we explicitly tell type checkers that nothing is exported # from this file so that when we re-export the old symbols # in `openai/__init__.py` they aren't added to the auto-complete # suggestions given by editors if TYPE_CHECKING: __all__: list[str] = [] else: __all__ = SYMBOLS __locals = locals() for symbol in SYMBOLS: __locals[symbol] = APIRemovedInV1Proxy(symbol=symbol) ================================================ FILE: src/openai/lib/_parsing/__init__.py ================================================ from ._completions import ( ResponseFormatT as ResponseFormatT, has_parseable_input, has_parseable_input as has_parseable_input, maybe_parse_content as maybe_parse_content, validate_input_tools as validate_input_tools, parse_chat_completion as parse_chat_completion, get_input_tool_by_name as get_input_tool_by_name, parse_function_tool_arguments as parse_function_tool_arguments, type_to_response_format_param as type_to_response_format_param, ) ================================================ FILE: src/openai/lib/_parsing/_completions.py ================================================ from __future__ import annotations import json import logging from typing import TYPE_CHECKING, Any, Iterable, cast from typing_extensions import TypeVar, TypeGuard, assert_never import pydantic from .._tools import PydanticFunctionTool from ..._types import Omit, omit from ..._utils import is_dict, is_given from ..._compat import PYDANTIC_V1, model_parse_json from ..._models import construct_type_unchecked from .._pydantic import is_basemodel_type, to_strict_json_schema, is_dataclass_like_type from ...types.chat import ( ParsedChoice, ChatCompletion, ParsedFunction, ParsedChatCompletion, ChatCompletionMessage, ParsedFunctionToolCall, ParsedChatCompletionMessage, ChatCompletionToolUnionParam, ChatCompletionFunctionToolParam, completion_create_params, ) from ..._exceptions import LengthFinishReasonError, ContentFilterFinishReasonError from ...types.shared_params import FunctionDefinition from ...types.chat.completion_create_params import ResponseFormat as ResponseFormatParam from ...types.chat.chat_completion_message_function_tool_call import Function ResponseFormatT = TypeVar( "ResponseFormatT", # if it isn't given then we don't do any parsing default=None, ) _default_response_format: None = None log: logging.Logger = logging.getLogger("openai.lib.parsing") def is_strict_chat_completion_tool_param( tool: ChatCompletionToolUnionParam, ) -> TypeGuard[ChatCompletionFunctionToolParam]: """Check if the given tool is a strict ChatCompletionFunctionToolParam.""" if not tool["type"] == "function": return False if tool["function"].get("strict") is not True: return False return True def select_strict_chat_completion_tools( tools: Iterable[ChatCompletionToolUnionParam] | Omit = omit, ) -> Iterable[ChatCompletionFunctionToolParam] | Omit: """Select only the strict ChatCompletionFunctionToolParams from the given tools.""" if not is_given(tools): return omit return [t for t in tools if is_strict_chat_completion_tool_param(t)] def validate_input_tools( tools: Iterable[ChatCompletionToolUnionParam] | Omit = omit, ) -> Iterable[ChatCompletionFunctionToolParam] | Omit: if not is_given(tools): return omit for tool in tools: if tool["type"] != "function": raise ValueError( f"Currently only `function` tool types support auto-parsing; Received `{tool['type']}`", ) strict = tool["function"].get("strict") if strict is not True: raise ValueError( f"`{tool['function']['name']}` is not strict. Only `strict` function tools can be auto-parsed" ) return cast(Iterable[ChatCompletionFunctionToolParam], tools) def parse_chat_completion( *, response_format: type[ResponseFormatT] | completion_create_params.ResponseFormat | Omit, input_tools: Iterable[ChatCompletionToolUnionParam] | Omit, chat_completion: ChatCompletion | ParsedChatCompletion[object], ) -> ParsedChatCompletion[ResponseFormatT]: if is_given(input_tools): input_tools = [t for t in input_tools] else: input_tools = [] choices: list[ParsedChoice[ResponseFormatT]] = [] for choice in chat_completion.choices: if choice.finish_reason == "length": raise LengthFinishReasonError(completion=chat_completion) if choice.finish_reason == "content_filter": raise ContentFilterFinishReasonError() message = choice.message tool_calls: list[ParsedFunctionToolCall] = [] if message.tool_calls: for tool_call in message.tool_calls: if tool_call.type == "function": tool_call_dict = tool_call.to_dict() tool_calls.append( construct_type_unchecked( value={ **tool_call_dict, "function": { **cast(Any, tool_call_dict["function"]), "parsed_arguments": parse_function_tool_arguments( input_tools=input_tools, function=tool_call.function ), }, }, type_=ParsedFunctionToolCall, ) ) elif tool_call.type == "custom": # warn user that custom tool calls are not callable here log.warning( "Custom tool calls are not callable. Ignoring tool call: %s - %s", tool_call.id, tool_call.custom.name, stacklevel=2, ) elif TYPE_CHECKING: # type: ignore[unreachable] assert_never(tool_call) else: tool_calls.append(tool_call) choices.append( construct_type_unchecked( type_=ParsedChoice[ResponseFormatT], value={ **choice.to_dict(), "message": { **message.to_dict(), "parsed": maybe_parse_content( response_format=response_format, message=message, ), "tool_calls": tool_calls if tool_calls else None, }, }, ) ) return construct_type_unchecked( type_=ParsedChatCompletion[ResponseFormatT], value={ **chat_completion.to_dict(), "choices": choices, }, ) def get_input_tool_by_name( *, input_tools: list[ChatCompletionToolUnionParam], name: str ) -> ChatCompletionFunctionToolParam | None: return next((t for t in input_tools if t["type"] == "function" and t.get("function", {}).get("name") == name), None) def parse_function_tool_arguments( *, input_tools: list[ChatCompletionToolUnionParam], function: Function | ParsedFunction ) -> object | None: input_tool = get_input_tool_by_name(input_tools=input_tools, name=function.name) if not input_tool: return None input_fn = cast(object, input_tool.get("function")) if isinstance(input_fn, PydanticFunctionTool): return model_parse_json(input_fn.model, function.arguments) input_fn = cast(FunctionDefinition, input_fn) if not input_fn.get("strict"): return None return json.loads(function.arguments) # type: ignore[no-any-return] def maybe_parse_content( *, response_format: type[ResponseFormatT] | ResponseFormatParam | Omit, message: ChatCompletionMessage | ParsedChatCompletionMessage[object], ) -> ResponseFormatT | None: if has_rich_response_format(response_format) and message.content and not message.refusal: return _parse_content(response_format, message.content) return None def has_parseable_input( *, response_format: type | ResponseFormatParam | Omit, input_tools: Iterable[ChatCompletionToolUnionParam] | Omit = omit, ) -> bool: if has_rich_response_format(response_format): return True for input_tool in input_tools or []: if is_parseable_tool(input_tool): return True return False def has_rich_response_format( response_format: type[ResponseFormatT] | ResponseFormatParam | Omit, ) -> TypeGuard[type[ResponseFormatT]]: if not is_given(response_format): return False if is_response_format_param(response_format): return False return True def is_response_format_param(response_format: object) -> TypeGuard[ResponseFormatParam]: return is_dict(response_format) def is_parseable_tool(input_tool: ChatCompletionToolUnionParam) -> bool: if input_tool["type"] != "function": return False input_fn = cast(object, input_tool.get("function")) if isinstance(input_fn, PydanticFunctionTool): return True return cast(FunctionDefinition, input_fn).get("strict") or False def _parse_content(response_format: type[ResponseFormatT], content: str) -> ResponseFormatT: if is_basemodel_type(response_format): return cast(ResponseFormatT, model_parse_json(response_format, content)) if is_dataclass_like_type(response_format): if PYDANTIC_V1: raise TypeError(f"Non BaseModel types are only supported with Pydantic v2 - {response_format}") return pydantic.TypeAdapter(response_format).validate_json(content) raise TypeError(f"Unable to automatically parse response format type {response_format}") def type_to_response_format_param( response_format: type | completion_create_params.ResponseFormat | Omit, ) -> ResponseFormatParam | Omit: if not is_given(response_format): return omit if is_response_format_param(response_format): return response_format # type checkers don't narrow the negation of a `TypeGuard` as it isn't # a safe default behaviour but we know that at this point the `response_format` # can only be a `type` response_format = cast(type, response_format) json_schema_type: type[pydantic.BaseModel] | pydantic.TypeAdapter[Any] | None = None if is_basemodel_type(response_format): name = response_format.__name__ json_schema_type = response_format elif is_dataclass_like_type(response_format): name = response_format.__name__ json_schema_type = pydantic.TypeAdapter(response_format) else: raise TypeError(f"Unsupported response_format type - {response_format}") return { "type": "json_schema", "json_schema": { "schema": to_strict_json_schema(json_schema_type), "name": name, "strict": True, }, } ================================================ FILE: src/openai/lib/_parsing/_responses.py ================================================ from __future__ import annotations import json from typing import TYPE_CHECKING, List, Iterable, cast from typing_extensions import TypeVar, assert_never import pydantic from .._tools import ResponsesPydanticFunctionTool from ..._types import Omit from ..._utils import is_given from ..._compat import PYDANTIC_V1, model_parse_json from ..._models import construct_type_unchecked from .._pydantic import is_basemodel_type, is_dataclass_like_type from ._completions import type_to_response_format_param from ...types.responses import ( Response, ToolParam, ParsedContent, ParsedResponse, FunctionToolParam, ParsedResponseOutputItem, ParsedResponseOutputText, ResponseFunctionToolCall, ParsedResponseOutputMessage, ResponseFormatTextConfigParam, ParsedResponseFunctionToolCall, ) from ...types.chat.completion_create_params import ResponseFormat TextFormatT = TypeVar( "TextFormatT", # if it isn't given then we don't do any parsing default=None, ) def type_to_text_format_param(type_: type) -> ResponseFormatTextConfigParam: response_format_dict = type_to_response_format_param(type_) assert is_given(response_format_dict) response_format_dict = cast(ResponseFormat, response_format_dict) # pyright: ignore[reportUnnecessaryCast] assert response_format_dict["type"] == "json_schema" assert "schema" in response_format_dict["json_schema"] return { "type": "json_schema", "strict": True, "name": response_format_dict["json_schema"]["name"], "schema": response_format_dict["json_schema"]["schema"], } def parse_response( *, text_format: type[TextFormatT] | Omit, input_tools: Iterable[ToolParam] | Omit | None, response: Response | ParsedResponse[object], ) -> ParsedResponse[TextFormatT]: output_list: List[ParsedResponseOutputItem[TextFormatT]] = [] for output in response.output: if output.type == "message": content_list: List[ParsedContent[TextFormatT]] = [] for item in output.content: if item.type != "output_text": content_list.append(item) continue content_list.append( construct_type_unchecked( type_=ParsedResponseOutputText[TextFormatT], value={ **item.to_dict(), "parsed": parse_text(item.text, text_format=text_format), }, ) ) output_list.append( construct_type_unchecked( type_=ParsedResponseOutputMessage[TextFormatT], value={ **output.to_dict(), "content": content_list, }, ) ) elif output.type == "function_call": output_list.append( construct_type_unchecked( type_=ParsedResponseFunctionToolCall, value={ **output.to_dict(), "parsed_arguments": parse_function_tool_arguments( input_tools=input_tools, function_call=output ), }, ) ) elif ( output.type == "computer_call" or output.type == "file_search_call" or output.type == "web_search_call" or output.type == "tool_search_call" or output.type == "tool_search_output" or output.type == "reasoning" or output.type == "compaction" or output.type == "mcp_call" or output.type == "mcp_approval_request" or output.type == "image_generation_call" or output.type == "code_interpreter_call" or output.type == "local_shell_call" or output.type == "shell_call" or output.type == "shell_call_output" or output.type == "apply_patch_call" or output.type == "apply_patch_call_output" or output.type == "mcp_list_tools" or output.type == "exec" or output.type == "custom_tool_call" ): output_list.append(output) elif TYPE_CHECKING: # type: ignore assert_never(output) else: output_list.append(output) return construct_type_unchecked( type_=ParsedResponse[TextFormatT], value={ **response.to_dict(), "output": output_list, }, ) def parse_text(text: str, text_format: type[TextFormatT] | Omit) -> TextFormatT | None: if not is_given(text_format): return None if is_basemodel_type(text_format): return cast(TextFormatT, model_parse_json(text_format, text)) if is_dataclass_like_type(text_format): if PYDANTIC_V1: raise TypeError(f"Non BaseModel types are only supported with Pydantic v2 - {text_format}") return pydantic.TypeAdapter(text_format).validate_json(text) raise TypeError(f"Unable to automatically parse response format type {text_format}") def get_input_tool_by_name(*, input_tools: Iterable[ToolParam], name: str) -> FunctionToolParam | None: for tool in input_tools: if tool["type"] == "function" and tool.get("name") == name: return tool return None def parse_function_tool_arguments( *, input_tools: Iterable[ToolParam] | Omit | None, function_call: ParsedResponseFunctionToolCall | ResponseFunctionToolCall, ) -> object: if input_tools is None or not is_given(input_tools): return None input_tool = get_input_tool_by_name(input_tools=input_tools, name=function_call.name) if not input_tool: return None tool = cast(object, input_tool) if isinstance(tool, ResponsesPydanticFunctionTool): return model_parse_json(tool.model, function_call.arguments) if not input_tool.get("strict"): return None return json.loads(function_call.arguments) ================================================ FILE: src/openai/lib/_pydantic.py ================================================ from __future__ import annotations import inspect from typing import Any, TypeVar from typing_extensions import TypeGuard import pydantic from .._types import NOT_GIVEN from .._utils import is_dict as _is_dict, is_list from .._compat import PYDANTIC_V1, model_json_schema _T = TypeVar("_T") def to_strict_json_schema(model: type[pydantic.BaseModel] | pydantic.TypeAdapter[Any]) -> dict[str, Any]: if inspect.isclass(model) and is_basemodel_type(model): schema = model_json_schema(model) elif (not PYDANTIC_V1) and isinstance(model, pydantic.TypeAdapter): schema = model.json_schema() else: raise TypeError(f"Non BaseModel types are only supported with Pydantic v2 - {model}") return _ensure_strict_json_schema(schema, path=(), root=schema) def _ensure_strict_json_schema( json_schema: object, *, path: tuple[str, ...], root: dict[str, object], ) -> dict[str, Any]: """Mutates the given JSON schema to ensure it conforms to the `strict` standard that the API expects. """ if not is_dict(json_schema): raise TypeError(f"Expected {json_schema} to be a dictionary; path={path}") defs = json_schema.get("$defs") if is_dict(defs): for def_name, def_schema in defs.items(): _ensure_strict_json_schema(def_schema, path=(*path, "$defs", def_name), root=root) definitions = json_schema.get("definitions") if is_dict(definitions): for definition_name, definition_schema in definitions.items(): _ensure_strict_json_schema(definition_schema, path=(*path, "definitions", definition_name), root=root) typ = json_schema.get("type") if typ == "object" and "additionalProperties" not in json_schema: json_schema["additionalProperties"] = False # object types # { 'type': 'object', 'properties': { 'a': {...} } } properties = json_schema.get("properties") if is_dict(properties): json_schema["required"] = [prop for prop in properties.keys()] json_schema["properties"] = { key: _ensure_strict_json_schema(prop_schema, path=(*path, "properties", key), root=root) for key, prop_schema in properties.items() } # arrays # { 'type': 'array', 'items': {...} } items = json_schema.get("items") if is_dict(items): json_schema["items"] = _ensure_strict_json_schema(items, path=(*path, "items"), root=root) # unions any_of = json_schema.get("anyOf") if is_list(any_of): json_schema["anyOf"] = [ _ensure_strict_json_schema(variant, path=(*path, "anyOf", str(i)), root=root) for i, variant in enumerate(any_of) ] # intersections all_of = json_schema.get("allOf") if is_list(all_of): if len(all_of) == 1: json_schema.update(_ensure_strict_json_schema(all_of[0], path=(*path, "allOf", "0"), root=root)) json_schema.pop("allOf") else: json_schema["allOf"] = [ _ensure_strict_json_schema(entry, path=(*path, "allOf", str(i)), root=root) for i, entry in enumerate(all_of) ] # strip `None` defaults as there's no meaningful distinction here # the schema will still be `nullable` and the model will default # to using `None` anyway if json_schema.get("default", NOT_GIVEN) is None: json_schema.pop("default") # we can't use `$ref`s if there are also other properties defined, e.g. # `{"$ref": "...", "description": "my description"}` # # so we unravel the ref # `{"type": "string", "description": "my description"}` ref = json_schema.get("$ref") if ref and has_more_than_n_keys(json_schema, 1): assert isinstance(ref, str), f"Received non-string $ref - {ref}" resolved = resolve_ref(root=root, ref=ref) if not is_dict(resolved): raise ValueError(f"Expected `$ref: {ref}` to resolved to a dictionary but got {resolved}") # properties from the json schema take priority over the ones on the `$ref` json_schema.update({**resolved, **json_schema}) json_schema.pop("$ref") # Since the schema expanded from `$ref` might not have `additionalProperties: false` applied, # we call `_ensure_strict_json_schema` again to fix the inlined schema and ensure it's valid. return _ensure_strict_json_schema(json_schema, path=path, root=root) return json_schema def resolve_ref(*, root: dict[str, object], ref: str) -> object: if not ref.startswith("#/"): raise ValueError(f"Unexpected $ref format {ref!r}; Does not start with #/") path = ref[2:].split("/") resolved = root for key in path: value = resolved[key] assert is_dict(value), f"encountered non-dictionary entry while resolving {ref} - {resolved}" resolved = value return resolved def is_basemodel_type(typ: type) -> TypeGuard[type[pydantic.BaseModel]]: if not inspect.isclass(typ): return False return issubclass(typ, pydantic.BaseModel) def is_dataclass_like_type(typ: type) -> bool: """Returns True if the given type likely used `@pydantic.dataclass`""" return hasattr(typ, "__pydantic_config__") def is_dict(obj: object) -> TypeGuard[dict[str, object]]: # just pretend that we know there are only `str` keys # as that check is not worth the performance cost return _is_dict(obj) def has_more_than_n_keys(obj: dict[str, object], n: int) -> bool: i = 0 for _ in obj.keys(): i += 1 if i > n: return True return False ================================================ FILE: src/openai/lib/_realtime.py ================================================ from __future__ import annotations import json from typing_extensions import override import httpx from openai import _legacy_response from openai._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from openai._utils import maybe_transform, async_maybe_transform from openai._base_client import make_request_options from openai.resources.realtime.calls import Calls, AsyncCalls from openai.types.realtime.realtime_session_create_request_param import RealtimeSessionCreateRequestParam __all__ = ["_Calls", "_AsyncCalls"] # Custom code to override the `create` method to have correct behavior with # application/sdp and multipart/form-data. # Ideally we can cutover to the generated code this overrides eventually and remove this. class _Calls(Calls): @override def create( self, *, sdp: str, session: RealtimeSessionCreateRequestParam | Omit = omit, extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: if session is omit: extra_headers = {"Accept": "application/sdp", "Content-Type": "application/sdp", **(extra_headers or {})} return self._post( "/realtime/calls", content=sdp.encode("utf-8"), options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, timeout=timeout), cast_to=_legacy_response.HttpxBinaryResponseContent, ) extra_headers = {"Accept": "application/sdp", "Content-Type": "multipart/form-data", **(extra_headers or {})} session_payload = maybe_transform(session, RealtimeSessionCreateRequestParam) files = [ ("sdp", (None, sdp.encode("utf-8"), "application/sdp")), ("session", (None, json.dumps(session_payload).encode("utf-8"), "application/json")), ] return self._post( "/realtime/calls", files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=_legacy_response.HttpxBinaryResponseContent, ) class _AsyncCalls(AsyncCalls): @override async def create( self, *, sdp: str, session: RealtimeSessionCreateRequestParam | Omit = omit, extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: if session is omit: extra_headers = {"Accept": "application/sdp", "Content-Type": "application/sdp", **(extra_headers or {})} return await self._post( "/realtime/calls", content=sdp.encode("utf-8"), options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, timeout=timeout), cast_to=_legacy_response.HttpxBinaryResponseContent, ) extra_headers = {"Accept": "application/sdp", "Content-Type": "multipart/form-data", **(extra_headers or {})} session_payload = await async_maybe_transform(session, RealtimeSessionCreateRequestParam) files = [ ("sdp", (None, sdp.encode("utf-8"), "application/sdp")), ("session", (None, json.dumps(session_payload).encode("utf-8"), "application/json")), ] return await self._post( "/realtime/calls", files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=_legacy_response.HttpxBinaryResponseContent, ) ================================================ FILE: src/openai/lib/_tools.py ================================================ from __future__ import annotations from typing import Any, Dict, cast import pydantic from ._pydantic import to_strict_json_schema from ..types.chat import ChatCompletionFunctionToolParam from ..types.shared_params import FunctionDefinition from ..types.responses.function_tool_param import FunctionToolParam as ResponsesFunctionToolParam class PydanticFunctionTool(Dict[str, Any]): """Dictionary wrapper so we can pass the given base model throughout the entire request stack without having to special case it. """ model: type[pydantic.BaseModel] def __init__(self, defn: FunctionDefinition, model: type[pydantic.BaseModel]) -> None: super().__init__(defn) self.model = model def cast(self) -> FunctionDefinition: return cast(FunctionDefinition, self) class ResponsesPydanticFunctionTool(Dict[str, Any]): model: type[pydantic.BaseModel] def __init__(self, tool: ResponsesFunctionToolParam, model: type[pydantic.BaseModel]) -> None: super().__init__(tool) self.model = model def cast(self) -> ResponsesFunctionToolParam: return cast(ResponsesFunctionToolParam, self) def pydantic_function_tool( model: type[pydantic.BaseModel], *, name: str | None = None, # inferred from class name by default description: str | None = None, # inferred from class docstring by default ) -> ChatCompletionFunctionToolParam: if description is None: # note: we intentionally don't use `.getdoc()` to avoid # including pydantic's docstrings description = model.__doc__ function = PydanticFunctionTool( { "name": name or model.__name__, "strict": True, "parameters": to_strict_json_schema(model), }, model, ).cast() if description is not None: function["description"] = description return { "type": "function", "function": function, } ================================================ FILE: src/openai/lib/_validators.py ================================================ # pyright: basic from __future__ import annotations import os import sys from typing import Any, TypeVar, Callable, Optional, NamedTuple from typing_extensions import TypeAlias from .._extras import pandas as pd class Remediation(NamedTuple): name: str immediate_msg: Optional[str] = None necessary_msg: Optional[str] = None necessary_fn: Optional[Callable[[Any], Any]] = None optional_msg: Optional[str] = None optional_fn: Optional[Callable[[Any], Any]] = None error_msg: Optional[str] = None OptionalDataFrameT = TypeVar("OptionalDataFrameT", bound="Optional[pd.DataFrame]") def num_examples_validator(df: pd.DataFrame) -> Remediation: """ This validator will only print out the number of examples and recommend to the user to increase the number of examples if less than 100. """ MIN_EXAMPLES = 100 optional_suggestion = ( "" if len(df) >= MIN_EXAMPLES else ". In general, we recommend having at least a few hundred examples. We've found that performance tends to linearly increase for every doubling of the number of examples" ) immediate_msg = f"\n- Your file contains {len(df)} prompt-completion pairs{optional_suggestion}" return Remediation(name="num_examples", immediate_msg=immediate_msg) def necessary_column_validator(df: pd.DataFrame, necessary_column: str) -> Remediation: """ This validator will ensure that the necessary column is present in the dataframe. """ def lower_case_column(df: pd.DataFrame, column: Any) -> pd.DataFrame: cols = [c for c in df.columns if str(c).lower() == column] df.rename(columns={cols[0]: column.lower()}, inplace=True) return df immediate_msg = None necessary_fn = None necessary_msg = None error_msg = None if necessary_column not in df.columns: if necessary_column in [str(c).lower() for c in df.columns]: def lower_case_column_creator(df: pd.DataFrame) -> pd.DataFrame: return lower_case_column(df, necessary_column) necessary_fn = lower_case_column_creator immediate_msg = f"\n- The `{necessary_column}` column/key should be lowercase" necessary_msg = f"Lower case column name to `{necessary_column}`" else: error_msg = f"`{necessary_column}` column/key is missing. Please make sure you name your columns/keys appropriately, then retry" return Remediation( name="necessary_column", immediate_msg=immediate_msg, necessary_msg=necessary_msg, necessary_fn=necessary_fn, error_msg=error_msg, ) def additional_column_validator(df: pd.DataFrame, fields: list[str] = ["prompt", "completion"]) -> Remediation: """ This validator will remove additional columns from the dataframe. """ additional_columns = [] necessary_msg = None immediate_msg = None necessary_fn = None # type: ignore if len(df.columns) > 2: additional_columns = [c for c in df.columns if c not in fields] warn_message = "" for ac in additional_columns: dups = [c for c in additional_columns if ac in c] if len(dups) > 0: warn_message += f"\n WARNING: Some of the additional columns/keys contain `{ac}` in their name. These will be ignored, and the column/key `{ac}` will be used instead. This could also result from a duplicate column/key in the provided file." immediate_msg = f"\n- The input file should contain exactly two columns/keys per row. Additional columns/keys present are: {additional_columns}{warn_message}" necessary_msg = f"Remove additional columns/keys: {additional_columns}" def necessary_fn(x: Any) -> Any: return x[fields] return Remediation( name="additional_column", immediate_msg=immediate_msg, necessary_msg=necessary_msg, necessary_fn=necessary_fn, ) def non_empty_field_validator(df: pd.DataFrame, field: str = "completion") -> Remediation: """ This validator will ensure that no completion is empty. """ necessary_msg = None necessary_fn = None # type: ignore immediate_msg = None if df[field].apply(lambda x: x == "").any() or df[field].isnull().any(): empty_rows = (df[field] == "") | (df[field].isnull()) empty_indexes = df.reset_index().index[empty_rows].tolist() immediate_msg = f"\n- `{field}` column/key should not contain empty strings. These are rows: {empty_indexes}" def necessary_fn(x: Any) -> Any: return x[x[field] != ""].dropna(subset=[field]) necessary_msg = f"Remove {len(empty_indexes)} rows with empty {field}s" return Remediation( name=f"empty_{field}", immediate_msg=immediate_msg, necessary_msg=necessary_msg, necessary_fn=necessary_fn, ) def duplicated_rows_validator(df: pd.DataFrame, fields: list[str] = ["prompt", "completion"]) -> Remediation: """ This validator will suggest to the user to remove duplicate rows if they exist. """ duplicated_rows = df.duplicated(subset=fields) duplicated_indexes = df.reset_index().index[duplicated_rows].tolist() immediate_msg = None optional_msg = None optional_fn = None # type: ignore if len(duplicated_indexes) > 0: immediate_msg = f"\n- There are {len(duplicated_indexes)} duplicated {'-'.join(fields)} sets. These are rows: {duplicated_indexes}" optional_msg = f"Remove {len(duplicated_indexes)} duplicate rows" def optional_fn(x: Any) -> Any: return x.drop_duplicates(subset=fields) return Remediation( name="duplicated_rows", immediate_msg=immediate_msg, optional_msg=optional_msg, optional_fn=optional_fn, ) def long_examples_validator(df: pd.DataFrame) -> Remediation: """ This validator will suggest to the user to remove examples that are too long. """ immediate_msg = None optional_msg = None optional_fn = None # type: ignore ft_type = infer_task_type(df) if ft_type != "open-ended generation": def get_long_indexes(d: pd.DataFrame) -> Any: long_examples = d.apply(lambda x: len(x.prompt) + len(x.completion) > 10000, axis=1) return d.reset_index().index[long_examples].tolist() long_indexes = get_long_indexes(df) if len(long_indexes) > 0: immediate_msg = f"\n- There are {len(long_indexes)} examples that are very long. These are rows: {long_indexes}\nFor conditional generation, and for classification the examples shouldn't be longer than 2048 tokens." optional_msg = f"Remove {len(long_indexes)} long examples" def optional_fn(x: Any) -> Any: long_indexes_to_drop = get_long_indexes(x) if long_indexes != long_indexes_to_drop: sys.stdout.write( f"The indices of the long examples has changed as a result of a previously applied recommendation.\nThe {len(long_indexes_to_drop)} long examples to be dropped are now at the following indices: {long_indexes_to_drop}\n" ) return x.drop(long_indexes_to_drop) return Remediation( name="long_examples", immediate_msg=immediate_msg, optional_msg=optional_msg, optional_fn=optional_fn, ) def common_prompt_suffix_validator(df: pd.DataFrame) -> Remediation: """ This validator will suggest to add a common suffix to the prompt if one doesn't already exist in case of classification or conditional generation. """ error_msg = None immediate_msg = None optional_msg = None optional_fn = None # type: ignore # Find a suffix which is not contained within the prompt otherwise suggested_suffix = "\n\n### =>\n\n" suffix_options = [ " ->", "\n\n###\n\n", "\n\n===\n\n", "\n\n---\n\n", "\n\n===>\n\n", "\n\n--->\n\n", ] for suffix_option in suffix_options: if suffix_option == " ->": if df.prompt.str.contains("\n").any(): continue if df.prompt.str.contains(suffix_option, regex=False).any(): continue suggested_suffix = suffix_option break display_suggested_suffix = suggested_suffix.replace("\n", "\\n") ft_type = infer_task_type(df) if ft_type == "open-ended generation": return Remediation(name="common_suffix") def add_suffix(x: Any, suffix: Any) -> Any: x["prompt"] += suffix return x common_suffix = get_common_xfix(df.prompt, xfix="suffix") if (df.prompt == common_suffix).all(): error_msg = f"All prompts are identical: `{common_suffix}`\nConsider leaving the prompts blank if you want to do open-ended generation, otherwise ensure prompts are different" return Remediation(name="common_suffix", error_msg=error_msg) if common_suffix != "": common_suffix_new_line_handled = common_suffix.replace("\n", "\\n") immediate_msg = f"\n- All prompts end with suffix `{common_suffix_new_line_handled}`" if len(common_suffix) > 10: immediate_msg += f". This suffix seems very long. Consider replacing with a shorter suffix, such as `{display_suggested_suffix}`" if df.prompt.str[: -len(common_suffix)].str.contains(common_suffix, regex=False).any(): immediate_msg += f"\n WARNING: Some of your prompts contain the suffix `{common_suffix}` more than once. We strongly suggest that you review your prompts and add a unique suffix" else: immediate_msg = "\n- Your data does not contain a common separator at the end of your prompts. Having a separator string appended to the end of the prompt makes it clearer to the fine-tuned model where the completion should begin. See https://platform.openai.com/docs/guides/fine-tuning/preparing-your-dataset for more detail and examples. If you intend to do open-ended generation, then you should leave the prompts empty" if common_suffix == "": optional_msg = f"Add a suffix separator `{display_suggested_suffix}` to all prompts" def optional_fn(x: Any) -> Any: return add_suffix(x, suggested_suffix) return Remediation( name="common_completion_suffix", immediate_msg=immediate_msg, optional_msg=optional_msg, optional_fn=optional_fn, error_msg=error_msg, ) def common_prompt_prefix_validator(df: pd.DataFrame) -> Remediation: """ This validator will suggest to remove a common prefix from the prompt if a long one exist. """ MAX_PREFIX_LEN = 12 immediate_msg = None optional_msg = None optional_fn = None # type: ignore common_prefix = get_common_xfix(df.prompt, xfix="prefix") if common_prefix == "": return Remediation(name="common_prefix") def remove_common_prefix(x: Any, prefix: Any) -> Any: x["prompt"] = x["prompt"].str[len(prefix) :] return x if (df.prompt == common_prefix).all(): # already handled by common_suffix_validator return Remediation(name="common_prefix") if common_prefix != "": immediate_msg = f"\n- All prompts start with prefix `{common_prefix}`" if MAX_PREFIX_LEN < len(common_prefix): immediate_msg += ". Fine-tuning doesn't require the instruction specifying the task, or a few-shot example scenario. Most of the time you should only add the input data into the prompt, and the desired output into the completion" optional_msg = f"Remove prefix `{common_prefix}` from all prompts" def optional_fn(x: Any) -> Any: return remove_common_prefix(x, common_prefix) return Remediation( name="common_prompt_prefix", immediate_msg=immediate_msg, optional_msg=optional_msg, optional_fn=optional_fn, ) def common_completion_prefix_validator(df: pd.DataFrame) -> Remediation: """ This validator will suggest to remove a common prefix from the completion if a long one exist. """ MAX_PREFIX_LEN = 5 common_prefix = get_common_xfix(df.completion, xfix="prefix") ws_prefix = len(common_prefix) > 0 and common_prefix[0] == " " if len(common_prefix) < MAX_PREFIX_LEN: return Remediation(name="common_prefix") def remove_common_prefix(x: Any, prefix: Any, ws_prefix: Any) -> Any: x["completion"] = x["completion"].str[len(prefix) :] if ws_prefix: # keep the single whitespace as prefix x["completion"] = f" {x['completion']}" return x if (df.completion == common_prefix).all(): # already handled by common_suffix_validator return Remediation(name="common_prefix") immediate_msg = f"\n- All completions start with prefix `{common_prefix}`. Most of the time you should only add the output data into the completion, without any prefix" optional_msg = f"Remove prefix `{common_prefix}` from all completions" def optional_fn(x: Any) -> Any: return remove_common_prefix(x, common_prefix, ws_prefix) return Remediation( name="common_completion_prefix", immediate_msg=immediate_msg, optional_msg=optional_msg, optional_fn=optional_fn, ) def common_completion_suffix_validator(df: pd.DataFrame) -> Remediation: """ This validator will suggest to add a common suffix to the completion if one doesn't already exist in case of classification or conditional generation. """ error_msg = None immediate_msg = None optional_msg = None optional_fn = None # type: ignore ft_type = infer_task_type(df) if ft_type == "open-ended generation" or ft_type == "classification": return Remediation(name="common_suffix") common_suffix = get_common_xfix(df.completion, xfix="suffix") if (df.completion == common_suffix).all(): error_msg = f"All completions are identical: `{common_suffix}`\nEnsure completions are different, otherwise the model will just repeat `{common_suffix}`" return Remediation(name="common_suffix", error_msg=error_msg) # Find a suffix which is not contained within the completion otherwise suggested_suffix = " [END]" suffix_options = [ "\n", ".", " END", "***", "+++", "&&&", "$$$", "@@@", "%%%", ] for suffix_option in suffix_options: if df.completion.str.contains(suffix_option, regex=False).any(): continue suggested_suffix = suffix_option break display_suggested_suffix = suggested_suffix.replace("\n", "\\n") def add_suffix(x: Any, suffix: Any) -> Any: x["completion"] += suffix return x if common_suffix != "": common_suffix_new_line_handled = common_suffix.replace("\n", "\\n") immediate_msg = f"\n- All completions end with suffix `{common_suffix_new_line_handled}`" if len(common_suffix) > 10: immediate_msg += f". This suffix seems very long. Consider replacing with a shorter suffix, such as `{display_suggested_suffix}`" if df.completion.str[: -len(common_suffix)].str.contains(common_suffix, regex=False).any(): immediate_msg += f"\n WARNING: Some of your completions contain the suffix `{common_suffix}` more than once. We suggest that you review your completions and add a unique ending" else: immediate_msg = "\n- Your data does not contain a common ending at the end of your completions. Having a common ending string appended to the end of the completion makes it clearer to the fine-tuned model where the completion should end. See https://platform.openai.com/docs/guides/fine-tuning/preparing-your-dataset for more detail and examples." if common_suffix == "": optional_msg = f"Add a suffix ending `{display_suggested_suffix}` to all completions" def optional_fn(x: Any) -> Any: return add_suffix(x, suggested_suffix) return Remediation( name="common_completion_suffix", immediate_msg=immediate_msg, optional_msg=optional_msg, optional_fn=optional_fn, error_msg=error_msg, ) def completions_space_start_validator(df: pd.DataFrame) -> Remediation: """ This validator will suggest to add a space at the start of the completion if it doesn't already exist. This helps with tokenization. """ def add_space_start(x: Any) -> Any: x["completion"] = x["completion"].apply(lambda s: ("" if s.startswith(" ") else " ") + s) return x optional_msg = None optional_fn = None immediate_msg = None if df.completion.str[:1].nunique() != 1 or df.completion.values[0][0] != " ": immediate_msg = "\n- The completion should start with a whitespace character (` `). This tends to produce better results due to the tokenization we use. See https://platform.openai.com/docs/guides/fine-tuning/preparing-your-dataset for more details" optional_msg = "Add a whitespace character to the beginning of the completion" optional_fn = add_space_start return Remediation( name="completion_space_start", immediate_msg=immediate_msg, optional_msg=optional_msg, optional_fn=optional_fn, ) def lower_case_validator(df: pd.DataFrame, column: Any) -> Remediation | None: """ This validator will suggest to lowercase the column values, if more than a third of letters are uppercase. """ def lower_case(x: Any) -> Any: x[column] = x[column].str.lower() return x count_upper = df[column].apply(lambda x: sum(1 for c in x if c.isalpha() and c.isupper())).sum() count_lower = df[column].apply(lambda x: sum(1 for c in x if c.isalpha() and c.islower())).sum() if count_upper * 2 > count_lower: return Remediation( name="lower_case", immediate_msg=f"\n- More than a third of your `{column}` column/key is uppercase. Uppercase {column}s tends to perform worse than a mixture of case encountered in normal language. We recommend to lower case the data if that makes sense in your domain. See https://platform.openai.com/docs/guides/fine-tuning/preparing-your-dataset for more details", optional_msg=f"Lowercase all your data in column/key `{column}`", optional_fn=lower_case, ) return None def read_any_format( fname: str, fields: list[str] = ["prompt", "completion"] ) -> tuple[pd.DataFrame | None, Remediation]: """ This function will read a file saved in .csv, .json, .txt, .xlsx or .tsv format using pandas. - for .xlsx it will read the first sheet - for .txt it will assume completions and split on newline """ remediation = None necessary_msg = None immediate_msg = None error_msg = None df = None if os.path.isfile(fname): try: if fname.lower().endswith(".csv") or fname.lower().endswith(".tsv"): file_extension_str, separator = ("CSV", ",") if fname.lower().endswith(".csv") else ("TSV", "\t") immediate_msg = ( f"\n- Based on your file extension, your file is formatted as a {file_extension_str} file" ) necessary_msg = f"Your format `{file_extension_str}` will be converted to `JSONL`" df = pd.read_csv(fname, sep=separator, dtype=str).fillna("") elif fname.lower().endswith(".xlsx"): immediate_msg = "\n- Based on your file extension, your file is formatted as an Excel file" necessary_msg = "Your format `XLSX` will be converted to `JSONL`" xls = pd.ExcelFile(fname) sheets = xls.sheet_names if len(sheets) > 1: immediate_msg += "\n- Your Excel file contains more than one sheet. Please either save as csv or ensure all data is present in the first sheet. WARNING: Reading only the first sheet..." df = pd.read_excel(fname, dtype=str).fillna("") elif fname.lower().endswith(".txt"): immediate_msg = "\n- Based on your file extension, you provided a text file" necessary_msg = "Your format `TXT` will be converted to `JSONL`" with open(fname, "r") as f: content = f.read() df = pd.DataFrame( [["", line] for line in content.split("\n")], columns=fields, dtype=str, ).fillna("") elif fname.lower().endswith(".jsonl"): df = pd.read_json(fname, lines=True, dtype=str).fillna("") # type: ignore if len(df) == 1: # type: ignore # this is NOT what we expect for a .jsonl file immediate_msg = "\n- Your JSONL file appears to be in a JSON format. Your file will be converted to JSONL format" necessary_msg = "Your format `JSON` will be converted to `JSONL`" df = pd.read_json(fname, dtype=str).fillna("") # type: ignore else: pass # this is what we expect for a .jsonl file elif fname.lower().endswith(".json"): try: # to handle case where .json file is actually a .jsonl file df = pd.read_json(fname, lines=True, dtype=str).fillna("") # type: ignore if len(df) == 1: # type: ignore # this code path corresponds to a .json file that has one line df = pd.read_json(fname, dtype=str).fillna("") # type: ignore else: # this is NOT what we expect for a .json file immediate_msg = "\n- Your JSON file appears to be in a JSONL format. Your file will be converted to JSONL format" necessary_msg = "Your format `JSON` will be converted to `JSONL`" except ValueError: # this code path corresponds to a .json file that has multiple lines (i.e. it is indented) df = pd.read_json(fname, dtype=str).fillna("") # type: ignore else: error_msg = ( "Your file must have one of the following extensions: .CSV, .TSV, .XLSX, .TXT, .JSON or .JSONL" ) if "." in fname: error_msg += f" Your file `{fname}` ends with the extension `.{fname.split('.')[-1]}` which is not supported." else: error_msg += f" Your file `{fname}` is missing a file extension." except (ValueError, TypeError): file_extension_str = fname.split(".")[-1].upper() error_msg = f"Your file `{fname}` does not appear to be in valid {file_extension_str} format. Please ensure your file is formatted as a valid {file_extension_str} file." else: error_msg = f"File {fname} does not exist." remediation = Remediation( name="read_any_format", necessary_msg=necessary_msg, immediate_msg=immediate_msg, error_msg=error_msg, ) return df, remediation def format_inferrer_validator(df: pd.DataFrame) -> Remediation: """ This validator will infer the likely fine-tuning format of the data, and display it to the user if it is classification. It will also suggest to use ada and explain train/validation split benefits. """ ft_type = infer_task_type(df) immediate_msg = None if ft_type == "classification": immediate_msg = f"\n- Based on your data it seems like you're trying to fine-tune a model for {ft_type}\n- For classification, we recommend you try one of the faster and cheaper models, such as `ada`\n- For classification, you can estimate the expected model performance by keeping a held out dataset, which is not used for training" return Remediation(name="num_examples", immediate_msg=immediate_msg) def apply_necessary_remediation(df: OptionalDataFrameT, remediation: Remediation) -> OptionalDataFrameT: """ This function will apply a necessary remediation to a dataframe, or print an error message if one exists. """ if remediation.error_msg is not None: sys.stderr.write(f"\n\nERROR in {remediation.name} validator: {remediation.error_msg}\n\nAborting...") sys.exit(1) if remediation.immediate_msg is not None: sys.stdout.write(remediation.immediate_msg) if remediation.necessary_fn is not None: df = remediation.necessary_fn(df) return df def accept_suggestion(input_text: str, auto_accept: bool) -> bool: sys.stdout.write(input_text) if auto_accept: sys.stdout.write("Y\n") return True return input().lower() != "n" def apply_optional_remediation( df: pd.DataFrame, remediation: Remediation, auto_accept: bool ) -> tuple[pd.DataFrame, bool]: """ This function will apply an optional remediation to a dataframe, based on the user input. """ optional_applied = False input_text = f"- [Recommended] {remediation.optional_msg} [Y/n]: " if remediation.optional_msg is not None: if accept_suggestion(input_text, auto_accept): assert remediation.optional_fn is not None df = remediation.optional_fn(df) optional_applied = True if remediation.necessary_msg is not None: sys.stdout.write(f"- [Necessary] {remediation.necessary_msg}\n") return df, optional_applied def estimate_fine_tuning_time(df: pd.DataFrame) -> None: """ Estimate the time it'll take to fine-tune the dataset """ ft_format = infer_task_type(df) expected_time = 1.0 if ft_format == "classification": num_examples = len(df) expected_time = num_examples * 1.44 else: size = df.memory_usage(index=True).sum() expected_time = size * 0.0515 def format_time(time: float) -> str: if time < 60: return f"{round(time, 2)} seconds" elif time < 3600: return f"{round(time / 60, 2)} minutes" elif time < 86400: return f"{round(time / 3600, 2)} hours" else: return f"{round(time / 86400, 2)} days" time_string = format_time(expected_time + 140) sys.stdout.write( f"Once your model starts training, it'll approximately take {time_string} to train a `curie` model, and less for `ada` and `babbage`. Queue will approximately take half an hour per job ahead of you.\n" ) def get_outfnames(fname: str, split: bool) -> list[str]: suffixes = ["_train", "_valid"] if split else [""] i = 0 while True: index_suffix = f" ({i})" if i > 0 else "" candidate_fnames = [f"{os.path.splitext(fname)[0]}_prepared{suffix}{index_suffix}.jsonl" for suffix in suffixes] if not any(os.path.isfile(f) for f in candidate_fnames): return candidate_fnames i += 1 def get_classification_hyperparams(df: pd.DataFrame) -> tuple[int, object]: n_classes = df.completion.nunique() pos_class = None if n_classes == 2: pos_class = df.completion.value_counts().index[0] return n_classes, pos_class def write_out_file(df: pd.DataFrame, fname: str, any_remediations: bool, auto_accept: bool) -> None: """ This function will write out a dataframe to a file, if the user would like to proceed, and also offer a fine-tuning command with the newly created file. For classification it will optionally ask the user if they would like to split the data into train/valid files, and modify the suggested command to include the valid set. """ ft_format = infer_task_type(df) common_prompt_suffix = get_common_xfix(df.prompt, xfix="suffix") common_completion_suffix = get_common_xfix(df.completion, xfix="suffix") split = False input_text = "- [Recommended] Would you like to split into training and validation set? [Y/n]: " if ft_format == "classification": if accept_suggestion(input_text, auto_accept): split = True additional_params = "" common_prompt_suffix_new_line_handled = common_prompt_suffix.replace("\n", "\\n") common_completion_suffix_new_line_handled = common_completion_suffix.replace("\n", "\\n") optional_ending_string = ( f' Make sure to include `stop=["{common_completion_suffix_new_line_handled}"]` so that the generated texts ends at the expected place.' if len(common_completion_suffix_new_line_handled) > 0 else "" ) input_text = "\n\nYour data will be written to a new JSONL file. Proceed [Y/n]: " if not any_remediations and not split: sys.stdout.write( f'\nYou can use your file for fine-tuning:\n> openai api fine_tunes.create -t "{fname}"{additional_params}\n\nAfter you’ve fine-tuned a model, remember that your prompt has to end with the indicator string `{common_prompt_suffix_new_line_handled}` for the model to start generating completions, rather than continuing with the prompt.{optional_ending_string}\n' ) estimate_fine_tuning_time(df) elif accept_suggestion(input_text, auto_accept): fnames = get_outfnames(fname, split) if split: assert len(fnames) == 2 and "train" in fnames[0] and "valid" in fnames[1] MAX_VALID_EXAMPLES = 1000 n_train = max(len(df) - MAX_VALID_EXAMPLES, int(len(df) * 0.8)) df_train = df.sample(n=n_train, random_state=42) df_valid = df.drop(df_train.index) df_train[["prompt", "completion"]].to_json( # type: ignore fnames[0], lines=True, orient="records", force_ascii=False, indent=None ) df_valid[["prompt", "completion"]].to_json( fnames[1], lines=True, orient="records", force_ascii=False, indent=None ) n_classes, pos_class = get_classification_hyperparams(df) additional_params += " --compute_classification_metrics" if n_classes == 2: additional_params += f' --classification_positive_class "{pos_class}"' else: additional_params += f" --classification_n_classes {n_classes}" else: assert len(fnames) == 1 df[["prompt", "completion"]].to_json( fnames[0], lines=True, orient="records", force_ascii=False, indent=None ) # Add -v VALID_FILE if we split the file into train / valid files_string = ("s" if split else "") + " to `" + ("` and `".join(fnames)) valid_string = f' -v "{fnames[1]}"' if split else "" separator_reminder = ( "" if len(common_prompt_suffix_new_line_handled) == 0 else f"After you’ve fine-tuned a model, remember that your prompt has to end with the indicator string `{common_prompt_suffix_new_line_handled}` for the model to start generating completions, rather than continuing with the prompt." ) sys.stdout.write( f'\nWrote modified file{files_string}`\nFeel free to take a look!\n\nNow use that file when fine-tuning:\n> openai api fine_tunes.create -t "{fnames[0]}"{valid_string}{additional_params}\n\n{separator_reminder}{optional_ending_string}\n' ) estimate_fine_tuning_time(df) else: sys.stdout.write("Aborting... did not write the file\n") def infer_task_type(df: pd.DataFrame) -> str: """ Infer the likely fine-tuning task type from the data """ CLASSIFICATION_THRESHOLD = 3 # min_average instances of each class if sum(df.prompt.str.len()) == 0: return "open-ended generation" if len(df.completion.unique()) < len(df) / CLASSIFICATION_THRESHOLD: return "classification" return "conditional generation" def get_common_xfix(series: Any, xfix: str = "suffix") -> str: """ Finds the longest common suffix or prefix of all the values in a series """ common_xfix = "" while True: common_xfixes = ( series.str[-(len(common_xfix) + 1) :] if xfix == "suffix" else series.str[: len(common_xfix) + 1] ) # first few or last few characters if common_xfixes.nunique() != 1: # we found the character at which we don't have a unique xfix anymore break elif common_xfix == common_xfixes.values[0]: # the entire first row is a prefix of every other row break else: # the first or last few characters are still common across all rows - let's try to add one more common_xfix = common_xfixes.values[0] return common_xfix Validator: TypeAlias = "Callable[[pd.DataFrame], Remediation | None]" def get_validators() -> list[Validator]: return [ num_examples_validator, lambda x: necessary_column_validator(x, "prompt"), lambda x: necessary_column_validator(x, "completion"), additional_column_validator, non_empty_field_validator, format_inferrer_validator, duplicated_rows_validator, long_examples_validator, lambda x: lower_case_validator(x, "prompt"), lambda x: lower_case_validator(x, "completion"), common_prompt_suffix_validator, common_prompt_prefix_validator, common_completion_prefix_validator, common_completion_suffix_validator, completions_space_start_validator, ] def apply_validators( df: pd.DataFrame, fname: str, remediation: Remediation | None, validators: list[Validator], auto_accept: bool, write_out_file_func: Callable[..., Any], ) -> None: optional_remediations: list[Remediation] = [] if remediation is not None: optional_remediations.append(remediation) for validator in validators: remediation = validator(df) if remediation is not None: optional_remediations.append(remediation) df = apply_necessary_remediation(df, remediation) any_optional_or_necessary_remediations = any( [ remediation for remediation in optional_remediations if remediation.optional_msg is not None or remediation.necessary_msg is not None ] ) any_necessary_applied = any( [remediation for remediation in optional_remediations if remediation.necessary_msg is not None] ) any_optional_applied = False if any_optional_or_necessary_remediations: sys.stdout.write("\n\nBased on the analysis we will perform the following actions:\n") for remediation in optional_remediations: df, optional_applied = apply_optional_remediation(df, remediation, auto_accept) any_optional_applied = any_optional_applied or optional_applied else: sys.stdout.write("\n\nNo remediations found.\n") any_optional_or_necessary_applied = any_optional_applied or any_necessary_applied write_out_file_func(df, fname, any_optional_or_necessary_applied, auto_accept) ================================================ FILE: src/openai/lib/azure.py ================================================ from __future__ import annotations import os import inspect from typing import Any, Union, Mapping, TypeVar, Callable, Awaitable, cast, overload from typing_extensions import Self, override import httpx from .._types import NOT_GIVEN, Omit, Query, Timeout, NotGiven from .._utils import is_given, is_mapping from .._client import OpenAI, AsyncOpenAI from .._compat import model_copy from .._models import FinalRequestOptions from .._streaming import Stream, AsyncStream from .._exceptions import OpenAIError from .._base_client import DEFAULT_MAX_RETRIES, BaseClient _deployments_endpoints = set( [ "/completions", "/chat/completions", "/embeddings", "/audio/transcriptions", "/audio/translations", "/audio/speech", "/images/generations", "/images/edits", ] ) AzureADTokenProvider = Callable[[], str] AsyncAzureADTokenProvider = Callable[[], "str | Awaitable[str]"] _HttpxClientT = TypeVar("_HttpxClientT", bound=Union[httpx.Client, httpx.AsyncClient]) _DefaultStreamT = TypeVar("_DefaultStreamT", bound=Union[Stream[Any], AsyncStream[Any]]) # we need to use a sentinel API key value for Azure AD # as we don't want to make the `api_key` in the main client Optional # and Azure AD tokens may be retrieved on a per-request basis API_KEY_SENTINEL = "".join(["<", "missing API key", ">"]) class MutuallyExclusiveAuthError(OpenAIError): def __init__(self) -> None: super().__init__( "The `api_key`, `azure_ad_token` and `azure_ad_token_provider` arguments are mutually exclusive; Only one can be passed at a time" ) class BaseAzureClient(BaseClient[_HttpxClientT, _DefaultStreamT]): _azure_endpoint: httpx.URL | None _azure_deployment: str | None @override def _build_request( self, options: FinalRequestOptions, *, retries_taken: int = 0, ) -> httpx.Request: if options.url in _deployments_endpoints and is_mapping(options.json_data): model = options.json_data.get("model") if model is not None and "/deployments" not in str(self.base_url.path): options.url = f"/deployments/{model}{options.url}" return super()._build_request(options, retries_taken=retries_taken) @override def _prepare_url(self, url: str) -> httpx.URL: """Adjust the URL if the client was configured with an Azure endpoint + deployment and the API feature being called is **not** a deployments-based endpoint (i.e. requires /deployments/deployment-name in the URL path). """ if self._azure_deployment and self._azure_endpoint and url not in _deployments_endpoints: merge_url = httpx.URL(url) if merge_url.is_relative_url: merge_raw_path = ( self._azure_endpoint.raw_path.rstrip(b"/") + b"/openai/" + merge_url.raw_path.lstrip(b"/") ) return self._azure_endpoint.copy_with(raw_path=merge_raw_path) return merge_url return super()._prepare_url(url) class AzureOpenAI(BaseAzureClient[httpx.Client, Stream[Any]], OpenAI): @overload def __init__( self, *, azure_endpoint: str, azure_deployment: str | None = None, api_version: str | None = None, api_key: str | Callable[[], str] | None = None, azure_ad_token: str | None = None, azure_ad_token_provider: AzureADTokenProvider | None = None, organization: str | None = None, webhook_secret: str | None = None, websocket_base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, http_client: httpx.Client | None = None, _strict_response_validation: bool = False, ) -> None: ... @overload def __init__( self, *, azure_deployment: str | None = None, api_version: str | None = None, api_key: str | Callable[[], str] | None = None, azure_ad_token: str | None = None, azure_ad_token_provider: AzureADTokenProvider | None = None, organization: str | None = None, webhook_secret: str | None = None, websocket_base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, http_client: httpx.Client | None = None, _strict_response_validation: bool = False, ) -> None: ... @overload def __init__( self, *, base_url: str, api_version: str | None = None, api_key: str | Callable[[], str] | None = None, azure_ad_token: str | None = None, azure_ad_token_provider: AzureADTokenProvider | None = None, organization: str | None = None, webhook_secret: str | None = None, websocket_base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, http_client: httpx.Client | None = None, _strict_response_validation: bool = False, ) -> None: ... def __init__( self, *, api_version: str | None = None, azure_endpoint: str | None = None, azure_deployment: str | None = None, api_key: str | Callable[[], str] | None = None, azure_ad_token: str | None = None, azure_ad_token_provider: AzureADTokenProvider | None = None, organization: str | None = None, project: str | None = None, webhook_secret: str | None = None, websocket_base_url: str | httpx.URL | None = None, base_url: str | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, http_client: httpx.Client | None = None, _strict_response_validation: bool = False, ) -> None: """Construct a new synchronous azure openai client instance. This automatically infers the following arguments from their corresponding environment variables if they are not provided: - `api_key` from `AZURE_OPENAI_API_KEY` - `organization` from `OPENAI_ORG_ID` - `project` from `OPENAI_PROJECT_ID` - `azure_ad_token` from `AZURE_OPENAI_AD_TOKEN` - `api_version` from `OPENAI_API_VERSION` - `azure_endpoint` from `AZURE_OPENAI_ENDPOINT` Args: azure_endpoint: Your Azure endpoint, including the resource, e.g. `https://example-resource.azure.openai.com/` azure_ad_token: Your Azure Active Directory token, https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-id azure_ad_token_provider: A function that returns an Azure Active Directory token, will be invoked on every request. azure_deployment: A model deployment, if given with `azure_endpoint`, sets the base client URL to include `/deployments/{azure_deployment}`. Not supported with Assistants APIs. """ if api_key is None: api_key = os.environ.get("AZURE_OPENAI_API_KEY") if azure_ad_token is None: azure_ad_token = os.environ.get("AZURE_OPENAI_AD_TOKEN") if api_key is None and azure_ad_token is None and azure_ad_token_provider is None: raise OpenAIError( "Missing credentials. Please pass one of `api_key`, `azure_ad_token`, `azure_ad_token_provider`, or the `AZURE_OPENAI_API_KEY` or `AZURE_OPENAI_AD_TOKEN` environment variables." ) if api_version is None: api_version = os.environ.get("OPENAI_API_VERSION") if api_version is None: raise ValueError( "Must provide either the `api_version` argument or the `OPENAI_API_VERSION` environment variable" ) if default_query is None: default_query = {"api-version": api_version} else: default_query = {**default_query, "api-version": api_version} if base_url is None: if azure_endpoint is None: azure_endpoint = os.environ.get("AZURE_OPENAI_ENDPOINT") if azure_endpoint is None: raise ValueError( "Must provide one of the `base_url` or `azure_endpoint` arguments, or the `AZURE_OPENAI_ENDPOINT` environment variable" ) if azure_deployment is not None: base_url = f"{azure_endpoint.rstrip('/')}/openai/deployments/{azure_deployment}" else: base_url = f"{azure_endpoint.rstrip('/')}/openai" else: if azure_endpoint is not None: raise ValueError("base_url and azure_endpoint are mutually exclusive") if api_key is None: # define a sentinel value to avoid any typing issues api_key = API_KEY_SENTINEL super().__init__( api_key=api_key, organization=organization, project=project, webhook_secret=webhook_secret, base_url=base_url, timeout=timeout, max_retries=max_retries, default_headers=default_headers, default_query=default_query, http_client=http_client, websocket_base_url=websocket_base_url, _strict_response_validation=_strict_response_validation, ) self._api_version = api_version self._azure_ad_token = azure_ad_token self._azure_ad_token_provider = azure_ad_token_provider self._azure_deployment = azure_deployment if azure_endpoint else None self._azure_endpoint = httpx.URL(azure_endpoint) if azure_endpoint else None @override def copy( self, *, api_key: str | Callable[[], str] | None = None, organization: str | None = None, project: str | None = None, webhook_secret: str | None = None, websocket_base_url: str | httpx.URL | None = None, api_version: str | None = None, azure_ad_token: str | None = None, azure_ad_token_provider: AzureADTokenProvider | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, http_client: httpx.Client | None = None, max_retries: int | NotGiven = NOT_GIVEN, default_headers: Mapping[str, str] | None = None, set_default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, set_default_query: Mapping[str, object] | None = None, _extra_kwargs: Mapping[str, Any] = {}, ) -> Self: """ Create a new client instance re-using the same options given to the current client with optional overriding. """ return super().copy( api_key=api_key, organization=organization, project=project, webhook_secret=webhook_secret, websocket_base_url=websocket_base_url, base_url=base_url, timeout=timeout, http_client=http_client, max_retries=max_retries, default_headers=default_headers, set_default_headers=set_default_headers, default_query=default_query, set_default_query=set_default_query, _extra_kwargs={ "api_version": api_version or self._api_version, "azure_ad_token": azure_ad_token or self._azure_ad_token, "azure_ad_token_provider": azure_ad_token_provider or self._azure_ad_token_provider, **_extra_kwargs, }, ) with_options = copy def _get_azure_ad_token(self) -> str | None: if self._azure_ad_token is not None: return self._azure_ad_token provider = self._azure_ad_token_provider if provider is not None: token = provider() if not token or not isinstance(token, str): # pyright: ignore[reportUnnecessaryIsInstance] raise ValueError( f"Expected `azure_ad_token_provider` argument to return a string but it returned {token}", ) return token return None @override def _prepare_options(self, options: FinalRequestOptions) -> FinalRequestOptions: headers: dict[str, str | Omit] = {**options.headers} if is_given(options.headers) else {} options = model_copy(options) options.headers = headers azure_ad_token = self._get_azure_ad_token() if azure_ad_token is not None: if headers.get("Authorization") is None: headers["Authorization"] = f"Bearer {azure_ad_token}" elif self.api_key is not API_KEY_SENTINEL: if headers.get("api-key") is None: headers["api-key"] = self.api_key else: # should never be hit raise ValueError("Unable to handle auth") return options def _configure_realtime(self, model: str, extra_query: Query) -> tuple[httpx.URL, dict[str, str]]: auth_headers = {} query = { **extra_query, "api-version": self._api_version, "deployment": self._azure_deployment or model, } if self.api_key and self.api_key != "": auth_headers = {"api-key": self.api_key} else: token = self._get_azure_ad_token() if token: auth_headers = {"Authorization": f"Bearer {token}"} if self.websocket_base_url is not None: base_url = httpx.URL(self.websocket_base_url) merge_raw_path = base_url.raw_path.rstrip(b"/") + b"/realtime" realtime_url = base_url.copy_with(raw_path=merge_raw_path) else: base_url = self._prepare_url("/realtime") realtime_url = base_url.copy_with(scheme="wss") url = realtime_url.copy_with(params={**query}) return url, auth_headers class AsyncAzureOpenAI(BaseAzureClient[httpx.AsyncClient, AsyncStream[Any]], AsyncOpenAI): @overload def __init__( self, *, azure_endpoint: str, azure_deployment: str | None = None, api_version: str | None = None, api_key: str | Callable[[], Awaitable[str]] | None = None, azure_ad_token: str | None = None, azure_ad_token_provider: AsyncAzureADTokenProvider | None = None, organization: str | None = None, project: str | None = None, webhook_secret: str | None = None, websocket_base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, http_client: httpx.AsyncClient | None = None, _strict_response_validation: bool = False, ) -> None: ... @overload def __init__( self, *, azure_deployment: str | None = None, api_version: str | None = None, api_key: str | Callable[[], Awaitable[str]] | None = None, azure_ad_token: str | None = None, azure_ad_token_provider: AsyncAzureADTokenProvider | None = None, organization: str | None = None, project: str | None = None, webhook_secret: str | None = None, websocket_base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, http_client: httpx.AsyncClient | None = None, _strict_response_validation: bool = False, ) -> None: ... @overload def __init__( self, *, base_url: str, api_version: str | None = None, api_key: str | Callable[[], Awaitable[str]] | None = None, azure_ad_token: str | None = None, azure_ad_token_provider: AsyncAzureADTokenProvider | None = None, organization: str | None = None, project: str | None = None, webhook_secret: str | None = None, websocket_base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, http_client: httpx.AsyncClient | None = None, _strict_response_validation: bool = False, ) -> None: ... def __init__( self, *, azure_endpoint: str | None = None, azure_deployment: str | None = None, api_version: str | None = None, api_key: str | Callable[[], Awaitable[str]] | None = None, azure_ad_token: str | None = None, azure_ad_token_provider: AsyncAzureADTokenProvider | None = None, organization: str | None = None, project: str | None = None, webhook_secret: str | None = None, base_url: str | None = None, websocket_base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, http_client: httpx.AsyncClient | None = None, _strict_response_validation: bool = False, ) -> None: """Construct a new asynchronous azure openai client instance. This automatically infers the following arguments from their corresponding environment variables if they are not provided: - `api_key` from `AZURE_OPENAI_API_KEY` - `organization` from `OPENAI_ORG_ID` - `project` from `OPENAI_PROJECT_ID` - `azure_ad_token` from `AZURE_OPENAI_AD_TOKEN` - `api_version` from `OPENAI_API_VERSION` - `azure_endpoint` from `AZURE_OPENAI_ENDPOINT` Args: azure_endpoint: Your Azure endpoint, including the resource, e.g. `https://example-resource.azure.openai.com/` azure_ad_token: Your Azure Active Directory token, https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-id azure_ad_token_provider: A function that returns an Azure Active Directory token, will be invoked on every request. azure_deployment: A model deployment, if given with `azure_endpoint`, sets the base client URL to include `/deployments/{azure_deployment}`. Not supported with Assistants APIs. """ if api_key is None: api_key = os.environ.get("AZURE_OPENAI_API_KEY") if azure_ad_token is None: azure_ad_token = os.environ.get("AZURE_OPENAI_AD_TOKEN") if api_key is None and azure_ad_token is None and azure_ad_token_provider is None: raise OpenAIError( "Missing credentials. Please pass one of `api_key`, `azure_ad_token`, `azure_ad_token_provider`, or the `AZURE_OPENAI_API_KEY` or `AZURE_OPENAI_AD_TOKEN` environment variables." ) if api_version is None: api_version = os.environ.get("OPENAI_API_VERSION") if api_version is None: raise ValueError( "Must provide either the `api_version` argument or the `OPENAI_API_VERSION` environment variable" ) if default_query is None: default_query = {"api-version": api_version} else: default_query = {**default_query, "api-version": api_version} if base_url is None: if azure_endpoint is None: azure_endpoint = os.environ.get("AZURE_OPENAI_ENDPOINT") if azure_endpoint is None: raise ValueError( "Must provide one of the `base_url` or `azure_endpoint` arguments, or the `AZURE_OPENAI_ENDPOINT` environment variable" ) if azure_deployment is not None: base_url = f"{azure_endpoint.rstrip('/')}/openai/deployments/{azure_deployment}" else: base_url = f"{azure_endpoint.rstrip('/')}/openai" else: if azure_endpoint is not None: raise ValueError("base_url and azure_endpoint are mutually exclusive") if api_key is None: # define a sentinel value to avoid any typing issues api_key = API_KEY_SENTINEL super().__init__( api_key=api_key, organization=organization, project=project, webhook_secret=webhook_secret, base_url=base_url, timeout=timeout, max_retries=max_retries, default_headers=default_headers, default_query=default_query, http_client=http_client, websocket_base_url=websocket_base_url, _strict_response_validation=_strict_response_validation, ) self._api_version = api_version self._azure_ad_token = azure_ad_token self._azure_ad_token_provider = azure_ad_token_provider self._azure_deployment = azure_deployment if azure_endpoint else None self._azure_endpoint = httpx.URL(azure_endpoint) if azure_endpoint else None @override def copy( self, *, api_key: str | Callable[[], Awaitable[str]] | None = None, organization: str | None = None, project: str | None = None, webhook_secret: str | None = None, websocket_base_url: str | httpx.URL | None = None, api_version: str | None = None, azure_ad_token: str | None = None, azure_ad_token_provider: AsyncAzureADTokenProvider | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, http_client: httpx.AsyncClient | None = None, max_retries: int | NotGiven = NOT_GIVEN, default_headers: Mapping[str, str] | None = None, set_default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, set_default_query: Mapping[str, object] | None = None, _extra_kwargs: Mapping[str, Any] = {}, ) -> Self: """ Create a new client instance re-using the same options given to the current client with optional overriding. """ return super().copy( api_key=api_key, organization=organization, project=project, webhook_secret=webhook_secret, websocket_base_url=websocket_base_url, base_url=base_url, timeout=timeout, http_client=http_client, max_retries=max_retries, default_headers=default_headers, set_default_headers=set_default_headers, default_query=default_query, set_default_query=set_default_query, _extra_kwargs={ "api_version": api_version or self._api_version, "azure_ad_token": azure_ad_token or self._azure_ad_token, "azure_ad_token_provider": azure_ad_token_provider or self._azure_ad_token_provider, **_extra_kwargs, }, ) with_options = copy async def _get_azure_ad_token(self) -> str | None: if self._azure_ad_token is not None: return self._azure_ad_token provider = self._azure_ad_token_provider if provider is not None: token = provider() if inspect.isawaitable(token): token = await token if not token or not isinstance(cast(Any, token), str): raise ValueError( f"Expected `azure_ad_token_provider` argument to return a string but it returned {token}", ) return str(token) return None @override async def _prepare_options(self, options: FinalRequestOptions) -> FinalRequestOptions: headers: dict[str, str | Omit] = {**options.headers} if is_given(options.headers) else {} options = model_copy(options) options.headers = headers azure_ad_token = await self._get_azure_ad_token() if azure_ad_token is not None: if headers.get("Authorization") is None: headers["Authorization"] = f"Bearer {azure_ad_token}" elif self.api_key is not API_KEY_SENTINEL: if headers.get("api-key") is None: headers["api-key"] = self.api_key else: # should never be hit raise ValueError("Unable to handle auth") return options async def _configure_realtime(self, model: str, extra_query: Query) -> tuple[httpx.URL, dict[str, str]]: auth_headers = {} query = { **extra_query, "api-version": self._api_version, "deployment": self._azure_deployment or model, } if self.api_key and self.api_key != "": auth_headers = {"api-key": self.api_key} else: token = await self._get_azure_ad_token() if token: auth_headers = {"Authorization": f"Bearer {token}"} if self.websocket_base_url is not None: base_url = httpx.URL(self.websocket_base_url) merge_raw_path = base_url.raw_path.rstrip(b"/") + b"/realtime" realtime_url = base_url.copy_with(raw_path=merge_raw_path) else: base_url = self._prepare_url("/realtime") realtime_url = base_url.copy_with(scheme="wss") url = realtime_url.copy_with(params={**query}) return url, auth_headers ================================================ FILE: src/openai/lib/streaming/__init__.py ================================================ from ._assistants import ( AssistantEventHandler as AssistantEventHandler, AssistantEventHandlerT as AssistantEventHandlerT, AssistantStreamManager as AssistantStreamManager, AsyncAssistantEventHandler as AsyncAssistantEventHandler, AsyncAssistantEventHandlerT as AsyncAssistantEventHandlerT, AsyncAssistantStreamManager as AsyncAssistantStreamManager, ) ================================================ FILE: src/openai/lib/streaming/_assistants.py ================================================ from __future__ import annotations import asyncio from types import TracebackType from typing import TYPE_CHECKING, Any, Generic, TypeVar, Callable, Iterable, Iterator, cast from typing_extensions import Awaitable, AsyncIterable, AsyncIterator, assert_never import httpx from ..._utils import is_dict, is_list, consume_sync_iterator, consume_async_iterator from ..._compat import model_dump from ..._models import construct_type from ..._streaming import Stream, AsyncStream from ...types.beta import AssistantStreamEvent from ...types.beta.threads import ( Run, Text, Message, ImageFile, TextDelta, MessageDelta, MessageContent, MessageContentDelta, ) from ...types.beta.threads.runs import RunStep, ToolCall, RunStepDelta, ToolCallDelta class AssistantEventHandler: text_deltas: Iterable[str] """Iterator over just the text deltas in the stream. This corresponds to the `thread.message.delta` event in the API. ```py for text in stream.text_deltas: print(text, end="", flush=True) print() ``` """ def __init__(self) -> None: self._current_event: AssistantStreamEvent | None = None self._current_message_content_index: int | None = None self._current_message_content: MessageContent | None = None self._current_tool_call_index: int | None = None self._current_tool_call: ToolCall | None = None self.__current_run_step_id: str | None = None self.__current_run: Run | None = None self.__run_step_snapshots: dict[str, RunStep] = {} self.__message_snapshots: dict[str, Message] = {} self.__current_message_snapshot: Message | None = None self.text_deltas = self.__text_deltas__() self._iterator = self.__stream__() self.__stream: Stream[AssistantStreamEvent] | None = None def _init(self, stream: Stream[AssistantStreamEvent]) -> None: if self.__stream: raise RuntimeError( "A single event handler cannot be shared between multiple streams; You will need to construct a new event handler instance" ) self.__stream = stream def __next__(self) -> AssistantStreamEvent: return self._iterator.__next__() def __iter__(self) -> Iterator[AssistantStreamEvent]: for item in self._iterator: yield item @property def current_event(self) -> AssistantStreamEvent | None: return self._current_event @property def current_run(self) -> Run | None: return self.__current_run @property def current_run_step_snapshot(self) -> RunStep | None: if not self.__current_run_step_id: return None return self.__run_step_snapshots[self.__current_run_step_id] @property def current_message_snapshot(self) -> Message | None: return self.__current_message_snapshot def close(self) -> None: """ Close the response and release the connection. Automatically called when the context manager exits. """ if self.__stream: self.__stream.close() def until_done(self) -> None: """Waits until the stream has been consumed""" consume_sync_iterator(self) def get_final_run(self) -> Run: """Wait for the stream to finish and returns the completed Run object""" self.until_done() if not self.__current_run: raise RuntimeError("No final run object found") return self.__current_run def get_final_run_steps(self) -> list[RunStep]: """Wait for the stream to finish and returns the steps taken in this run""" self.until_done() if not self.__run_step_snapshots: raise RuntimeError("No run steps found") return [step for step in self.__run_step_snapshots.values()] def get_final_messages(self) -> list[Message]: """Wait for the stream to finish and returns the messages emitted in this run""" self.until_done() if not self.__message_snapshots: raise RuntimeError("No messages found") return [message for message in self.__message_snapshots.values()] def __text_deltas__(self) -> Iterator[str]: for event in self: if event.event != "thread.message.delta": continue for content_delta in event.data.delta.content or []: if content_delta.type == "text" and content_delta.text and content_delta.text.value: yield content_delta.text.value # event handlers def on_end(self) -> None: """Fires when the stream has finished. This happens if the stream is read to completion or if an exception occurs during iteration. """ def on_event(self, event: AssistantStreamEvent) -> None: """Callback that is fired for every Server-Sent-Event""" def on_run_step_created(self, run_step: RunStep) -> None: """Callback that is fired when a run step is created""" def on_run_step_delta(self, delta: RunStepDelta, snapshot: RunStep) -> None: """Callback that is fired whenever a run step delta is returned from the API The first argument is just the delta as sent by the API and the second argument is the accumulated snapshot of the run step. For example, a tool calls event may look like this: # delta tool_calls=[ RunStepDeltaToolCallsCodeInterpreter( index=0, type='code_interpreter', id=None, code_interpreter=CodeInterpreter(input=' sympy', outputs=None) ) ] # snapshot tool_calls=[ CodeToolCall( id='call_wKayJlcYV12NiadiZuJXxcfx', code_interpreter=CodeInterpreter(input='from sympy', outputs=[]), type='code_interpreter', index=0 ) ], """ def on_run_step_done(self, run_step: RunStep) -> None: """Callback that is fired when a run step is completed""" def on_tool_call_created(self, tool_call: ToolCall) -> None: """Callback that is fired when a tool call is created""" def on_tool_call_delta(self, delta: ToolCallDelta, snapshot: ToolCall) -> None: """Callback that is fired when a tool call delta is encountered""" def on_tool_call_done(self, tool_call: ToolCall) -> None: """Callback that is fired when a tool call delta is encountered""" def on_exception(self, exception: Exception) -> None: """Fired whenever an exception happens during streaming""" def on_timeout(self) -> None: """Fires if the request times out""" def on_message_created(self, message: Message) -> None: """Callback that is fired when a message is created""" def on_message_delta(self, delta: MessageDelta, snapshot: Message) -> None: """Callback that is fired whenever a message delta is returned from the API The first argument is just the delta as sent by the API and the second argument is the accumulated snapshot of the message. For example, a text content event may look like this: # delta MessageDeltaText( index=0, type='text', text=Text( value=' Jane' ), ) # snapshot MessageContentText( index=0, type='text', text=Text( value='Certainly, Jane' ), ) """ def on_message_done(self, message: Message) -> None: """Callback that is fired when a message is completed""" def on_text_created(self, text: Text) -> None: """Callback that is fired when a text content block is created""" def on_text_delta(self, delta: TextDelta, snapshot: Text) -> None: """Callback that is fired whenever a text content delta is returned by the API. The first argument is just the delta as sent by the API and the second argument is the accumulated snapshot of the text. For example: on_text_delta(TextDelta(value="The"), Text(value="The")), on_text_delta(TextDelta(value=" solution"), Text(value="The solution")), on_text_delta(TextDelta(value=" to"), Text(value="The solution to")), on_text_delta(TextDelta(value=" the"), Text(value="The solution to the")), on_text_delta(TextDelta(value=" equation"), Text(value="The solution to the equation")), """ def on_text_done(self, text: Text) -> None: """Callback that is fired when a text content block is finished""" def on_image_file_done(self, image_file: ImageFile) -> None: """Callback that is fired when an image file block is finished""" def _emit_sse_event(self, event: AssistantStreamEvent) -> None: self._current_event = event self.on_event(event) self.__current_message_snapshot, new_content = accumulate_event( event=event, current_message_snapshot=self.__current_message_snapshot, ) if self.__current_message_snapshot is not None: self.__message_snapshots[self.__current_message_snapshot.id] = self.__current_message_snapshot accumulate_run_step( event=event, run_step_snapshots=self.__run_step_snapshots, ) for content_delta in new_content: assert self.__current_message_snapshot is not None block = self.__current_message_snapshot.content[content_delta.index] if block.type == "text": self.on_text_created(block.text) if ( event.event == "thread.run.completed" or event.event == "thread.run.cancelled" or event.event == "thread.run.expired" or event.event == "thread.run.failed" or event.event == "thread.run.requires_action" or event.event == "thread.run.incomplete" ): self.__current_run = event.data if self._current_tool_call: self.on_tool_call_done(self._current_tool_call) elif ( event.event == "thread.run.created" or event.event == "thread.run.in_progress" or event.event == "thread.run.cancelling" or event.event == "thread.run.queued" ): self.__current_run = event.data elif event.event == "thread.message.created": self.on_message_created(event.data) elif event.event == "thread.message.delta": snapshot = self.__current_message_snapshot assert snapshot is not None message_delta = event.data.delta if message_delta.content is not None: for content_delta in message_delta.content: if content_delta.type == "text" and content_delta.text: snapshot_content = snapshot.content[content_delta.index] assert snapshot_content.type == "text" self.on_text_delta(content_delta.text, snapshot_content.text) # If the delta is for a new message content: # - emit on_text_done/on_image_file_done for the previous message content # - emit on_text_created/on_image_created for the new message content if content_delta.index != self._current_message_content_index: if self._current_message_content is not None: if self._current_message_content.type == "text": self.on_text_done(self._current_message_content.text) elif self._current_message_content.type == "image_file": self.on_image_file_done(self._current_message_content.image_file) self._current_message_content_index = content_delta.index self._current_message_content = snapshot.content[content_delta.index] # Update the current_message_content (delta event is correctly emitted already) self._current_message_content = snapshot.content[content_delta.index] self.on_message_delta(event.data.delta, snapshot) elif event.event == "thread.message.completed" or event.event == "thread.message.incomplete": self.__current_message_snapshot = event.data self.__message_snapshots[event.data.id] = event.data if self._current_message_content_index is not None: content = event.data.content[self._current_message_content_index] if content.type == "text": self.on_text_done(content.text) elif content.type == "image_file": self.on_image_file_done(content.image_file) self.on_message_done(event.data) elif event.event == "thread.run.step.created": self.__current_run_step_id = event.data.id self.on_run_step_created(event.data) elif event.event == "thread.run.step.in_progress": self.__current_run_step_id = event.data.id elif event.event == "thread.run.step.delta": step_snapshot = self.__run_step_snapshots[event.data.id] run_step_delta = event.data.delta if ( run_step_delta.step_details and run_step_delta.step_details.type == "tool_calls" and run_step_delta.step_details.tool_calls is not None ): assert step_snapshot.step_details.type == "tool_calls" for tool_call_delta in run_step_delta.step_details.tool_calls: if tool_call_delta.index == self._current_tool_call_index: self.on_tool_call_delta( tool_call_delta, step_snapshot.step_details.tool_calls[tool_call_delta.index], ) # If the delta is for a new tool call: # - emit on_tool_call_done for the previous tool_call # - emit on_tool_call_created for the new tool_call if tool_call_delta.index != self._current_tool_call_index: if self._current_tool_call is not None: self.on_tool_call_done(self._current_tool_call) self._current_tool_call_index = tool_call_delta.index self._current_tool_call = step_snapshot.step_details.tool_calls[tool_call_delta.index] self.on_tool_call_created(self._current_tool_call) # Update the current_tool_call (delta event is correctly emitted already) self._current_tool_call = step_snapshot.step_details.tool_calls[tool_call_delta.index] self.on_run_step_delta( event.data.delta, step_snapshot, ) elif ( event.event == "thread.run.step.completed" or event.event == "thread.run.step.cancelled" or event.event == "thread.run.step.expired" or event.event == "thread.run.step.failed" ): if self._current_tool_call: self.on_tool_call_done(self._current_tool_call) self.on_run_step_done(event.data) self.__current_run_step_id = None elif event.event == "thread.created" or event.event == "thread.message.in_progress" or event.event == "error": # currently no special handling ... else: # we only want to error at build-time if TYPE_CHECKING: # type: ignore[unreachable] assert_never(event) self._current_event = None def __stream__(self) -> Iterator[AssistantStreamEvent]: stream = self.__stream if not stream: raise RuntimeError("Stream has not been started yet") try: for event in stream: self._emit_sse_event(event) yield event except (httpx.TimeoutException, asyncio.TimeoutError) as exc: self.on_timeout() self.on_exception(exc) raise except Exception as exc: self.on_exception(exc) raise finally: self.on_end() AssistantEventHandlerT = TypeVar("AssistantEventHandlerT", bound=AssistantEventHandler) class AssistantStreamManager(Generic[AssistantEventHandlerT]): """Wrapper over AssistantStreamEventHandler that is returned by `.stream()` so that a context manager can be used. ```py with client.threads.create_and_run_stream(...) as stream: for event in stream: ... ``` """ def __init__( self, api_request: Callable[[], Stream[AssistantStreamEvent]], *, event_handler: AssistantEventHandlerT, ) -> None: self.__stream: Stream[AssistantStreamEvent] | None = None self.__event_handler = event_handler self.__api_request = api_request def __enter__(self) -> AssistantEventHandlerT: self.__stream = self.__api_request() self.__event_handler._init(self.__stream) return self.__event_handler def __exit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None, ) -> None: if self.__stream is not None: self.__stream.close() class AsyncAssistantEventHandler: text_deltas: AsyncIterable[str] """Iterator over just the text deltas in the stream. This corresponds to the `thread.message.delta` event in the API. ```py async for text in stream.text_deltas: print(text, end="", flush=True) print() ``` """ def __init__(self) -> None: self._current_event: AssistantStreamEvent | None = None self._current_message_content_index: int | None = None self._current_message_content: MessageContent | None = None self._current_tool_call_index: int | None = None self._current_tool_call: ToolCall | None = None self.__current_run_step_id: str | None = None self.__current_run: Run | None = None self.__run_step_snapshots: dict[str, RunStep] = {} self.__message_snapshots: dict[str, Message] = {} self.__current_message_snapshot: Message | None = None self.text_deltas = self.__text_deltas__() self._iterator = self.__stream__() self.__stream: AsyncStream[AssistantStreamEvent] | None = None def _init(self, stream: AsyncStream[AssistantStreamEvent]) -> None: if self.__stream: raise RuntimeError( "A single event handler cannot be shared between multiple streams; You will need to construct a new event handler instance" ) self.__stream = stream async def __anext__(self) -> AssistantStreamEvent: return await self._iterator.__anext__() async def __aiter__(self) -> AsyncIterator[AssistantStreamEvent]: async for item in self._iterator: yield item async def close(self) -> None: """ Close the response and release the connection. Automatically called when the context manager exits. """ if self.__stream: await self.__stream.close() @property def current_event(self) -> AssistantStreamEvent | None: return self._current_event @property def current_run(self) -> Run | None: return self.__current_run @property def current_run_step_snapshot(self) -> RunStep | None: if not self.__current_run_step_id: return None return self.__run_step_snapshots[self.__current_run_step_id] @property def current_message_snapshot(self) -> Message | None: return self.__current_message_snapshot async def until_done(self) -> None: """Waits until the stream has been consumed""" await consume_async_iterator(self) async def get_final_run(self) -> Run: """Wait for the stream to finish and returns the completed Run object""" await self.until_done() if not self.__current_run: raise RuntimeError("No final run object found") return self.__current_run async def get_final_run_steps(self) -> list[RunStep]: """Wait for the stream to finish and returns the steps taken in this run""" await self.until_done() if not self.__run_step_snapshots: raise RuntimeError("No run steps found") return [step for step in self.__run_step_snapshots.values()] async def get_final_messages(self) -> list[Message]: """Wait for the stream to finish and returns the messages emitted in this run""" await self.until_done() if not self.__message_snapshots: raise RuntimeError("No messages found") return [message for message in self.__message_snapshots.values()] async def __text_deltas__(self) -> AsyncIterator[str]: async for event in self: if event.event != "thread.message.delta": continue for content_delta in event.data.delta.content or []: if content_delta.type == "text" and content_delta.text and content_delta.text.value: yield content_delta.text.value # event handlers async def on_end(self) -> None: """Fires when the stream has finished. This happens if the stream is read to completion or if an exception occurs during iteration. """ async def on_event(self, event: AssistantStreamEvent) -> None: """Callback that is fired for every Server-Sent-Event""" async def on_run_step_created(self, run_step: RunStep) -> None: """Callback that is fired when a run step is created""" async def on_run_step_delta(self, delta: RunStepDelta, snapshot: RunStep) -> None: """Callback that is fired whenever a run step delta is returned from the API The first argument is just the delta as sent by the API and the second argument is the accumulated snapshot of the run step. For example, a tool calls event may look like this: # delta tool_calls=[ RunStepDeltaToolCallsCodeInterpreter( index=0, type='code_interpreter', id=None, code_interpreter=CodeInterpreter(input=' sympy', outputs=None) ) ] # snapshot tool_calls=[ CodeToolCall( id='call_wKayJlcYV12NiadiZuJXxcfx', code_interpreter=CodeInterpreter(input='from sympy', outputs=[]), type='code_interpreter', index=0 ) ], """ async def on_run_step_done(self, run_step: RunStep) -> None: """Callback that is fired when a run step is completed""" async def on_tool_call_created(self, tool_call: ToolCall) -> None: """Callback that is fired when a tool call is created""" async def on_tool_call_delta(self, delta: ToolCallDelta, snapshot: ToolCall) -> None: """Callback that is fired when a tool call delta is encountered""" async def on_tool_call_done(self, tool_call: ToolCall) -> None: """Callback that is fired when a tool call delta is encountered""" async def on_exception(self, exception: Exception) -> None: """Fired whenever an exception happens during streaming""" async def on_timeout(self) -> None: """Fires if the request times out""" async def on_message_created(self, message: Message) -> None: """Callback that is fired when a message is created""" async def on_message_delta(self, delta: MessageDelta, snapshot: Message) -> None: """Callback that is fired whenever a message delta is returned from the API The first argument is just the delta as sent by the API and the second argument is the accumulated snapshot of the message. For example, a text content event may look like this: # delta MessageDeltaText( index=0, type='text', text=Text( value=' Jane' ), ) # snapshot MessageContentText( index=0, type='text', text=Text( value='Certainly, Jane' ), ) """ async def on_message_done(self, message: Message) -> None: """Callback that is fired when a message is completed""" async def on_text_created(self, text: Text) -> None: """Callback that is fired when a text content block is created""" async def on_text_delta(self, delta: TextDelta, snapshot: Text) -> None: """Callback that is fired whenever a text content delta is returned by the API. The first argument is just the delta as sent by the API and the second argument is the accumulated snapshot of the text. For example: on_text_delta(TextDelta(value="The"), Text(value="The")), on_text_delta(TextDelta(value=" solution"), Text(value="The solution")), on_text_delta(TextDelta(value=" to"), Text(value="The solution to")), on_text_delta(TextDelta(value=" the"), Text(value="The solution to the")), on_text_delta(TextDelta(value=" equation"), Text(value="The solution to the equivalent")), """ async def on_text_done(self, text: Text) -> None: """Callback that is fired when a text content block is finished""" async def on_image_file_done(self, image_file: ImageFile) -> None: """Callback that is fired when an image file block is finished""" async def _emit_sse_event(self, event: AssistantStreamEvent) -> None: self._current_event = event await self.on_event(event) self.__current_message_snapshot, new_content = accumulate_event( event=event, current_message_snapshot=self.__current_message_snapshot, ) if self.__current_message_snapshot is not None: self.__message_snapshots[self.__current_message_snapshot.id] = self.__current_message_snapshot accumulate_run_step( event=event, run_step_snapshots=self.__run_step_snapshots, ) for content_delta in new_content: assert self.__current_message_snapshot is not None block = self.__current_message_snapshot.content[content_delta.index] if block.type == "text": await self.on_text_created(block.text) if ( event.event == "thread.run.completed" or event.event == "thread.run.cancelled" or event.event == "thread.run.expired" or event.event == "thread.run.failed" or event.event == "thread.run.requires_action" or event.event == "thread.run.incomplete" ): self.__current_run = event.data if self._current_tool_call: await self.on_tool_call_done(self._current_tool_call) elif ( event.event == "thread.run.created" or event.event == "thread.run.in_progress" or event.event == "thread.run.cancelling" or event.event == "thread.run.queued" ): self.__current_run = event.data elif event.event == "thread.message.created": await self.on_message_created(event.data) elif event.event == "thread.message.delta": snapshot = self.__current_message_snapshot assert snapshot is not None message_delta = event.data.delta if message_delta.content is not None: for content_delta in message_delta.content: if content_delta.type == "text" and content_delta.text: snapshot_content = snapshot.content[content_delta.index] assert snapshot_content.type == "text" await self.on_text_delta(content_delta.text, snapshot_content.text) # If the delta is for a new message content: # - emit on_text_done/on_image_file_done for the previous message content # - emit on_text_created/on_image_created for the new message content if content_delta.index != self._current_message_content_index: if self._current_message_content is not None: if self._current_message_content.type == "text": await self.on_text_done(self._current_message_content.text) elif self._current_message_content.type == "image_file": await self.on_image_file_done(self._current_message_content.image_file) self._current_message_content_index = content_delta.index self._current_message_content = snapshot.content[content_delta.index] # Update the current_message_content (delta event is correctly emitted already) self._current_message_content = snapshot.content[content_delta.index] await self.on_message_delta(event.data.delta, snapshot) elif event.event == "thread.message.completed" or event.event == "thread.message.incomplete": self.__current_message_snapshot = event.data self.__message_snapshots[event.data.id] = event.data if self._current_message_content_index is not None: content = event.data.content[self._current_message_content_index] if content.type == "text": await self.on_text_done(content.text) elif content.type == "image_file": await self.on_image_file_done(content.image_file) await self.on_message_done(event.data) elif event.event == "thread.run.step.created": self.__current_run_step_id = event.data.id await self.on_run_step_created(event.data) elif event.event == "thread.run.step.in_progress": self.__current_run_step_id = event.data.id elif event.event == "thread.run.step.delta": step_snapshot = self.__run_step_snapshots[event.data.id] run_step_delta = event.data.delta if ( run_step_delta.step_details and run_step_delta.step_details.type == "tool_calls" and run_step_delta.step_details.tool_calls is not None ): assert step_snapshot.step_details.type == "tool_calls" for tool_call_delta in run_step_delta.step_details.tool_calls: if tool_call_delta.index == self._current_tool_call_index: await self.on_tool_call_delta( tool_call_delta, step_snapshot.step_details.tool_calls[tool_call_delta.index], ) # If the delta is for a new tool call: # - emit on_tool_call_done for the previous tool_call # - emit on_tool_call_created for the new tool_call if tool_call_delta.index != self._current_tool_call_index: if self._current_tool_call is not None: await self.on_tool_call_done(self._current_tool_call) self._current_tool_call_index = tool_call_delta.index self._current_tool_call = step_snapshot.step_details.tool_calls[tool_call_delta.index] await self.on_tool_call_created(self._current_tool_call) # Update the current_tool_call (delta event is correctly emitted already) self._current_tool_call = step_snapshot.step_details.tool_calls[tool_call_delta.index] await self.on_run_step_delta( event.data.delta, step_snapshot, ) elif ( event.event == "thread.run.step.completed" or event.event == "thread.run.step.cancelled" or event.event == "thread.run.step.expired" or event.event == "thread.run.step.failed" ): if self._current_tool_call: await self.on_tool_call_done(self._current_tool_call) await self.on_run_step_done(event.data) self.__current_run_step_id = None elif event.event == "thread.created" or event.event == "thread.message.in_progress" or event.event == "error": # currently no special handling ... else: # we only want to error at build-time if TYPE_CHECKING: # type: ignore[unreachable] assert_never(event) self._current_event = None async def __stream__(self) -> AsyncIterator[AssistantStreamEvent]: stream = self.__stream if not stream: raise RuntimeError("Stream has not been started yet") try: async for event in stream: await self._emit_sse_event(event) yield event except (httpx.TimeoutException, asyncio.TimeoutError) as exc: await self.on_timeout() await self.on_exception(exc) raise except Exception as exc: await self.on_exception(exc) raise finally: await self.on_end() AsyncAssistantEventHandlerT = TypeVar("AsyncAssistantEventHandlerT", bound=AsyncAssistantEventHandler) class AsyncAssistantStreamManager(Generic[AsyncAssistantEventHandlerT]): """Wrapper over AsyncAssistantStreamEventHandler that is returned by `.stream()` so that an async context manager can be used without `await`ing the original client call. ```py async with client.threads.create_and_run_stream(...) as stream: async for event in stream: ... ``` """ def __init__( self, api_request: Awaitable[AsyncStream[AssistantStreamEvent]], *, event_handler: AsyncAssistantEventHandlerT, ) -> None: self.__stream: AsyncStream[AssistantStreamEvent] | None = None self.__event_handler = event_handler self.__api_request = api_request async def __aenter__(self) -> AsyncAssistantEventHandlerT: self.__stream = await self.__api_request self.__event_handler._init(self.__stream) return self.__event_handler async def __aexit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None, ) -> None: if self.__stream is not None: await self.__stream.close() def accumulate_run_step( *, event: AssistantStreamEvent, run_step_snapshots: dict[str, RunStep], ) -> None: if event.event == "thread.run.step.created": run_step_snapshots[event.data.id] = event.data return if event.event == "thread.run.step.delta": data = event.data snapshot = run_step_snapshots[data.id] if data.delta: merged = accumulate_delta( cast( "dict[object, object]", model_dump(snapshot, exclude_unset=True, warnings=False), ), cast( "dict[object, object]", model_dump(data.delta, exclude_unset=True, warnings=False), ), ) run_step_snapshots[snapshot.id] = cast(RunStep, construct_type(type_=RunStep, value=merged)) return None def accumulate_event( *, event: AssistantStreamEvent, current_message_snapshot: Message | None, ) -> tuple[Message | None, list[MessageContentDelta]]: """Returns a tuple of message snapshot and newly created text message deltas""" if event.event == "thread.message.created": return event.data, [] new_content: list[MessageContentDelta] = [] if event.event != "thread.message.delta": return current_message_snapshot, [] if not current_message_snapshot: raise RuntimeError("Encountered a message delta with no previous snapshot") data = event.data if data.delta.content: for content_delta in data.delta.content: try: block = current_message_snapshot.content[content_delta.index] except IndexError: current_message_snapshot.content.insert( content_delta.index, cast( MessageContent, construct_type( # mypy doesn't allow Content for some reason type_=cast(Any, MessageContent), value=model_dump(content_delta, exclude_unset=True, warnings=False), ), ), ) new_content.append(content_delta) else: merged = accumulate_delta( cast( "dict[object, object]", model_dump(block, exclude_unset=True, warnings=False), ), cast( "dict[object, object]", model_dump(content_delta, exclude_unset=True, warnings=False), ), ) current_message_snapshot.content[content_delta.index] = cast( MessageContent, construct_type( # mypy doesn't allow Content for some reason type_=cast(Any, MessageContent), value=merged, ), ) return current_message_snapshot, new_content def accumulate_delta(acc: dict[object, object], delta: dict[object, object]) -> dict[object, object]: for key, delta_value in delta.items(): if key not in acc: acc[key] = delta_value continue acc_value = acc[key] if acc_value is None: acc[key] = delta_value continue # the `index` property is used in arrays of objects so it should # not be accumulated like other values e.g. # [{'foo': 'bar', 'index': 0}] # # the same applies to `type` properties as they're used for # discriminated unions if key == "index" or key == "type": acc[key] = delta_value continue if isinstance(acc_value, str) and isinstance(delta_value, str): acc_value += delta_value elif isinstance(acc_value, (int, float)) and isinstance(delta_value, (int, float)): acc_value += delta_value elif is_dict(acc_value) and is_dict(delta_value): acc_value = accumulate_delta(acc_value, delta_value) elif is_list(acc_value) and is_list(delta_value): # for lists of non-dictionary items we'll only ever get new entries # in the array, existing entries will never be changed if all(isinstance(x, (str, int, float)) for x in acc_value): acc_value.extend(delta_value) continue for delta_entry in delta_value: if not is_dict(delta_entry): raise TypeError(f"Unexpected list delta entry is not a dictionary: {delta_entry}") try: index = delta_entry["index"] except KeyError as exc: raise RuntimeError(f"Expected list delta entry to have an `index` key; {delta_entry}") from exc if not isinstance(index, int): raise TypeError(f"Unexpected, list delta entry `index` value is not an integer; {index}") try: acc_entry = acc_value[index] except IndexError: acc_value.insert(index, delta_entry) else: if not is_dict(acc_entry): raise TypeError("not handled yet") acc_value[index] = accumulate_delta(acc_entry, delta_entry) acc[key] = acc_value return acc ================================================ FILE: src/openai/lib/streaming/_deltas.py ================================================ from __future__ import annotations from ..._utils import is_dict, is_list def accumulate_delta(acc: dict[object, object], delta: dict[object, object]) -> dict[object, object]: for key, delta_value in delta.items(): if key not in acc: acc[key] = delta_value continue acc_value = acc[key] if acc_value is None: acc[key] = delta_value continue # the `index` property is used in arrays of objects so it should # not be accumulated like other values e.g. # [{'foo': 'bar', 'index': 0}] # # the same applies to `type` properties as they're used for # discriminated unions if key == "index" or key == "type": acc[key] = delta_value continue if isinstance(acc_value, str) and isinstance(delta_value, str): acc_value += delta_value elif isinstance(acc_value, (int, float)) and isinstance(delta_value, (int, float)): acc_value += delta_value elif is_dict(acc_value) and is_dict(delta_value): acc_value = accumulate_delta(acc_value, delta_value) elif is_list(acc_value) and is_list(delta_value): # for lists of non-dictionary items we'll only ever get new entries # in the array, existing entries will never be changed if all(isinstance(x, (str, int, float)) for x in acc_value): acc_value.extend(delta_value) continue for delta_entry in delta_value: if not is_dict(delta_entry): raise TypeError(f"Unexpected list delta entry is not a dictionary: {delta_entry}") try: index = delta_entry["index"] except KeyError as exc: raise RuntimeError(f"Expected list delta entry to have an `index` key; {delta_entry}") from exc if not isinstance(index, int): raise TypeError(f"Unexpected, list delta entry `index` value is not an integer; {index}") try: acc_entry = acc_value[index] except IndexError: acc_value.insert(index, delta_entry) else: if not is_dict(acc_entry): raise TypeError("not handled yet") acc_value[index] = accumulate_delta(acc_entry, delta_entry) acc[key] = acc_value return acc ================================================ FILE: src/openai/lib/streaming/chat/__init__.py ================================================ from ._types import ( ParsedChoiceSnapshot as ParsedChoiceSnapshot, ParsedChatCompletionSnapshot as ParsedChatCompletionSnapshot, ParsedChatCompletionMessageSnapshot as ParsedChatCompletionMessageSnapshot, ) from ._events import ( ChunkEvent as ChunkEvent, ContentDoneEvent as ContentDoneEvent, RefusalDoneEvent as RefusalDoneEvent, ContentDeltaEvent as ContentDeltaEvent, RefusalDeltaEvent as RefusalDeltaEvent, LogprobsContentDoneEvent as LogprobsContentDoneEvent, LogprobsRefusalDoneEvent as LogprobsRefusalDoneEvent, ChatCompletionStreamEvent as ChatCompletionStreamEvent, LogprobsContentDeltaEvent as LogprobsContentDeltaEvent, LogprobsRefusalDeltaEvent as LogprobsRefusalDeltaEvent, ParsedChatCompletionSnapshot as ParsedChatCompletionSnapshot, FunctionToolCallArgumentsDoneEvent as FunctionToolCallArgumentsDoneEvent, FunctionToolCallArgumentsDeltaEvent as FunctionToolCallArgumentsDeltaEvent, ) from ._completions import ( ChatCompletionStream as ChatCompletionStream, AsyncChatCompletionStream as AsyncChatCompletionStream, ChatCompletionStreamState as ChatCompletionStreamState, ChatCompletionStreamManager as ChatCompletionStreamManager, AsyncChatCompletionStreamManager as AsyncChatCompletionStreamManager, ) ================================================ FILE: src/openai/lib/streaming/chat/_completions.py ================================================ from __future__ import annotations import inspect from types import TracebackType from typing import TYPE_CHECKING, Any, Generic, Callable, Iterable, Awaitable, AsyncIterator, cast from typing_extensions import Self, Iterator, assert_never from jiter import from_json from ._types import ParsedChoiceSnapshot, ParsedChatCompletionSnapshot, ParsedChatCompletionMessageSnapshot from ._events import ( ChunkEvent, ContentDoneEvent, RefusalDoneEvent, ContentDeltaEvent, RefusalDeltaEvent, LogprobsContentDoneEvent, LogprobsRefusalDoneEvent, ChatCompletionStreamEvent, LogprobsContentDeltaEvent, LogprobsRefusalDeltaEvent, FunctionToolCallArgumentsDoneEvent, FunctionToolCallArgumentsDeltaEvent, ) from .._deltas import accumulate_delta from ...._types import Omit, IncEx, omit from ...._utils import is_given, consume_sync_iterator, consume_async_iterator from ...._compat import model_dump from ...._models import build, construct_type from ..._parsing import ( ResponseFormatT, has_parseable_input, maybe_parse_content, parse_chat_completion, get_input_tool_by_name, parse_function_tool_arguments, ) from ...._streaming import Stream, AsyncStream from ....types.chat import ChatCompletionChunk, ParsedChatCompletion, ChatCompletionToolUnionParam from ...._exceptions import LengthFinishReasonError, ContentFilterFinishReasonError from ....types.chat.chat_completion import ChoiceLogprobs from ....types.chat.chat_completion_chunk import Choice as ChoiceChunk from ....types.chat.completion_create_params import ResponseFormat as ResponseFormatParam class ChatCompletionStream(Generic[ResponseFormatT]): """Wrapper over the Chat Completions streaming API that adds helpful events such as `content.done`, supports automatically parsing responses & tool calls and accumulates a `ChatCompletion` object from each individual chunk. https://platform.openai.com/docs/api-reference/streaming """ def __init__( self, *, raw_stream: Stream[ChatCompletionChunk], response_format: type[ResponseFormatT] | ResponseFormatParam | Omit, input_tools: Iterable[ChatCompletionToolUnionParam] | Omit, ) -> None: self._raw_stream = raw_stream self._response = raw_stream.response self._iterator = self.__stream__() self._state = ChatCompletionStreamState(response_format=response_format, input_tools=input_tools) def __next__(self) -> ChatCompletionStreamEvent[ResponseFormatT]: return self._iterator.__next__() def __iter__(self) -> Iterator[ChatCompletionStreamEvent[ResponseFormatT]]: for item in self._iterator: yield item def __enter__(self) -> Self: return self def __exit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None, ) -> None: self.close() def close(self) -> None: """ Close the response and release the connection. Automatically called if the response body is read to completion. """ self._response.close() def get_final_completion(self) -> ParsedChatCompletion[ResponseFormatT]: """Waits until the stream has been read to completion and returns the accumulated `ParsedChatCompletion` object. If you passed a class type to `.stream()`, the `completion.choices[0].message.parsed` property will be the content deserialised into that class, if there was any content returned by the API. """ self.until_done() return self._state.get_final_completion() def until_done(self) -> Self: """Blocks until the stream has been consumed.""" consume_sync_iterator(self) return self @property def current_completion_snapshot(self) -> ParsedChatCompletionSnapshot: return self._state.current_completion_snapshot def __stream__(self) -> Iterator[ChatCompletionStreamEvent[ResponseFormatT]]: for sse_event in self._raw_stream: if not _is_valid_chat_completion_chunk_weak(sse_event): continue events_to_fire = self._state.handle_chunk(sse_event) for event in events_to_fire: yield event class ChatCompletionStreamManager(Generic[ResponseFormatT]): """Context manager over a `ChatCompletionStream` that is returned by `.stream()`. This context manager ensures the response cannot be leaked if you don't read the stream to completion. Usage: ```py with client.chat.completions.stream(...) as stream: for event in stream: ... ``` """ def __init__( self, api_request: Callable[[], Stream[ChatCompletionChunk]], *, response_format: type[ResponseFormatT] | ResponseFormatParam | Omit, input_tools: Iterable[ChatCompletionToolUnionParam] | Omit, ) -> None: self.__stream: ChatCompletionStream[ResponseFormatT] | None = None self.__api_request = api_request self.__response_format = response_format self.__input_tools = input_tools def __enter__(self) -> ChatCompletionStream[ResponseFormatT]: raw_stream = self.__api_request() self.__stream = ChatCompletionStream( raw_stream=raw_stream, response_format=self.__response_format, input_tools=self.__input_tools, ) return self.__stream def __exit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None, ) -> None: if self.__stream is not None: self.__stream.close() class AsyncChatCompletionStream(Generic[ResponseFormatT]): """Wrapper over the Chat Completions streaming API that adds helpful events such as `content.done`, supports automatically parsing responses & tool calls and accumulates a `ChatCompletion` object from each individual chunk. https://platform.openai.com/docs/api-reference/streaming """ def __init__( self, *, raw_stream: AsyncStream[ChatCompletionChunk], response_format: type[ResponseFormatT] | ResponseFormatParam | Omit, input_tools: Iterable[ChatCompletionToolUnionParam] | Omit, ) -> None: self._raw_stream = raw_stream self._response = raw_stream.response self._iterator = self.__stream__() self._state = ChatCompletionStreamState(response_format=response_format, input_tools=input_tools) async def __anext__(self) -> ChatCompletionStreamEvent[ResponseFormatT]: return await self._iterator.__anext__() async def __aiter__(self) -> AsyncIterator[ChatCompletionStreamEvent[ResponseFormatT]]: async for item in self._iterator: yield item async def __aenter__(self) -> Self: return self async def __aexit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None, ) -> None: await self.close() async def close(self) -> None: """ Close the response and release the connection. Automatically called if the response body is read to completion. """ await self._response.aclose() async def get_final_completion(self) -> ParsedChatCompletion[ResponseFormatT]: """Waits until the stream has been read to completion and returns the accumulated `ParsedChatCompletion` object. If you passed a class type to `.stream()`, the `completion.choices[0].message.parsed` property will be the content deserialised into that class, if there was any content returned by the API. """ await self.until_done() return self._state.get_final_completion() async def until_done(self) -> Self: """Blocks until the stream has been consumed.""" await consume_async_iterator(self) return self @property def current_completion_snapshot(self) -> ParsedChatCompletionSnapshot: return self._state.current_completion_snapshot async def __stream__(self) -> AsyncIterator[ChatCompletionStreamEvent[ResponseFormatT]]: async for sse_event in self._raw_stream: if not _is_valid_chat_completion_chunk_weak(sse_event): continue events_to_fire = self._state.handle_chunk(sse_event) for event in events_to_fire: yield event class AsyncChatCompletionStreamManager(Generic[ResponseFormatT]): """Context manager over a `AsyncChatCompletionStream` that is returned by `.stream()`. This context manager ensures the response cannot be leaked if you don't read the stream to completion. Usage: ```py async with client.chat.completions.stream(...) as stream: for event in stream: ... ``` """ def __init__( self, api_request: Awaitable[AsyncStream[ChatCompletionChunk]], *, response_format: type[ResponseFormatT] | ResponseFormatParam | Omit, input_tools: Iterable[ChatCompletionToolUnionParam] | Omit, ) -> None: self.__stream: AsyncChatCompletionStream[ResponseFormatT] | None = None self.__api_request = api_request self.__response_format = response_format self.__input_tools = input_tools async def __aenter__(self) -> AsyncChatCompletionStream[ResponseFormatT]: raw_stream = await self.__api_request self.__stream = AsyncChatCompletionStream( raw_stream=raw_stream, response_format=self.__response_format, input_tools=self.__input_tools, ) return self.__stream async def __aexit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None, ) -> None: if self.__stream is not None: await self.__stream.close() class ChatCompletionStreamState(Generic[ResponseFormatT]): """Helper class for manually accumulating `ChatCompletionChunk`s into a final `ChatCompletion` object. This is useful in cases where you can't always use the `.stream()` method, e.g. ```py from openai.lib.streaming.chat import ChatCompletionStreamState state = ChatCompletionStreamState() stream = client.chat.completions.create(..., stream=True) for chunk in response: state.handle_chunk(chunk) # can also access the accumulated `ChatCompletion` mid-stream state.current_completion_snapshot print(state.get_final_completion()) ``` """ def __init__( self, *, input_tools: Iterable[ChatCompletionToolUnionParam] | Omit = omit, response_format: type[ResponseFormatT] | ResponseFormatParam | Omit = omit, ) -> None: self.__current_completion_snapshot: ParsedChatCompletionSnapshot | None = None self.__choice_event_states: list[ChoiceEventState] = [] self._input_tools = [tool for tool in input_tools] if is_given(input_tools) else [] self._response_format = response_format self._rich_response_format: type | Omit = response_format if inspect.isclass(response_format) else omit def get_final_completion(self) -> ParsedChatCompletion[ResponseFormatT]: """Parse the final completion object. Note this does not provide any guarantees that the stream has actually finished, you must only call this method when the stream is finished. """ return parse_chat_completion( chat_completion=self.current_completion_snapshot, response_format=self._rich_response_format, input_tools=self._input_tools, ) @property def current_completion_snapshot(self) -> ParsedChatCompletionSnapshot: assert self.__current_completion_snapshot is not None return self.__current_completion_snapshot def handle_chunk(self, chunk: ChatCompletionChunk) -> Iterable[ChatCompletionStreamEvent[ResponseFormatT]]: """Accumulate a new chunk into the snapshot and returns an iterable of events to yield.""" self.__current_completion_snapshot = self._accumulate_chunk(chunk) return self._build_events( chunk=chunk, completion_snapshot=self.__current_completion_snapshot, ) def _get_choice_state(self, choice: ChoiceChunk) -> ChoiceEventState: try: return self.__choice_event_states[choice.index] except IndexError: choice_state = ChoiceEventState(input_tools=self._input_tools) self.__choice_event_states.append(choice_state) return choice_state def _accumulate_chunk(self, chunk: ChatCompletionChunk) -> ParsedChatCompletionSnapshot: completion_snapshot = self.__current_completion_snapshot if completion_snapshot is None: return _convert_initial_chunk_into_snapshot(chunk) for choice in chunk.choices: try: choice_snapshot = completion_snapshot.choices[choice.index] previous_tool_calls = choice_snapshot.message.tool_calls or [] choice_snapshot.message = cast( ParsedChatCompletionMessageSnapshot, construct_type( type_=ParsedChatCompletionMessageSnapshot, value=accumulate_delta( cast( "dict[object, object]", model_dump( choice_snapshot.message, # we don't want to serialise / deserialise our custom properties # as they won't appear in the delta and we don't want to have to # continuosly reparse the content exclude=cast( # cast required as mypy isn't smart enough to infer `True` here to `Literal[True]` IncEx, { "parsed": True, "tool_calls": { idx: {"function": {"parsed_arguments": True}} for idx, _ in enumerate(choice_snapshot.message.tool_calls or []) }, }, ), ), ), cast("dict[object, object]", choice.delta.to_dict()), ), ), ) # ensure tools that have already been parsed are added back into the newly # constructed message snapshot for tool_index, prev_tool in enumerate(previous_tool_calls): new_tool = (choice_snapshot.message.tool_calls or [])[tool_index] if prev_tool.type == "function": assert new_tool.type == "function" new_tool.function.parsed_arguments = prev_tool.function.parsed_arguments elif TYPE_CHECKING: # type: ignore[unreachable] assert_never(prev_tool) except IndexError: choice_snapshot = cast( ParsedChoiceSnapshot, construct_type( type_=ParsedChoiceSnapshot, value={ **choice.model_dump(exclude_unset=True, exclude={"delta"}), "message": choice.delta.to_dict(), }, ), ) completion_snapshot.choices.append(choice_snapshot) if choice.finish_reason: choice_snapshot.finish_reason = choice.finish_reason if has_parseable_input(response_format=self._response_format, input_tools=self._input_tools): if choice.finish_reason == "length": # at the time of writing, `.usage` will always be `None` but # we include it here in case that is changed in the future raise LengthFinishReasonError(completion=completion_snapshot) if choice.finish_reason == "content_filter": raise ContentFilterFinishReasonError() if ( choice_snapshot.message.content and not choice_snapshot.message.refusal and is_given(self._rich_response_format) # partial parsing fails on white-space and choice_snapshot.message.content.lstrip() ): choice_snapshot.message.parsed = from_json( bytes(choice_snapshot.message.content, "utf-8"), partial_mode=True, ) for tool_call_chunk in choice.delta.tool_calls or []: tool_call_snapshot = (choice_snapshot.message.tool_calls or [])[tool_call_chunk.index] if tool_call_snapshot.type == "function": input_tool = get_input_tool_by_name( input_tools=self._input_tools, name=tool_call_snapshot.function.name ) if ( input_tool and input_tool.get("function", {}).get("strict") and tool_call_snapshot.function.arguments ): tool_call_snapshot.function.parsed_arguments = from_json( bytes(tool_call_snapshot.function.arguments, "utf-8"), partial_mode=True, ) elif TYPE_CHECKING: # type: ignore[unreachable] assert_never(tool_call_snapshot) if choice.logprobs is not None: if choice_snapshot.logprobs is None: choice_snapshot.logprobs = build( ChoiceLogprobs, content=choice.logprobs.content, refusal=choice.logprobs.refusal, ) else: if choice.logprobs.content: if choice_snapshot.logprobs.content is None: choice_snapshot.logprobs.content = [] choice_snapshot.logprobs.content.extend(choice.logprobs.content) if choice.logprobs.refusal: if choice_snapshot.logprobs.refusal is None: choice_snapshot.logprobs.refusal = [] choice_snapshot.logprobs.refusal.extend(choice.logprobs.refusal) completion_snapshot.usage = chunk.usage completion_snapshot.system_fingerprint = chunk.system_fingerprint return completion_snapshot def _build_events( self, *, chunk: ChatCompletionChunk, completion_snapshot: ParsedChatCompletionSnapshot, ) -> list[ChatCompletionStreamEvent[ResponseFormatT]]: events_to_fire: list[ChatCompletionStreamEvent[ResponseFormatT]] = [] events_to_fire.append( build(ChunkEvent, type="chunk", chunk=chunk, snapshot=completion_snapshot), ) for choice in chunk.choices: choice_state = self._get_choice_state(choice) choice_snapshot = completion_snapshot.choices[choice.index] if choice.delta.content is not None and choice_snapshot.message.content is not None: events_to_fire.append( build( ContentDeltaEvent, type="content.delta", delta=choice.delta.content, snapshot=choice_snapshot.message.content, parsed=choice_snapshot.message.parsed, ) ) if choice.delta.refusal is not None and choice_snapshot.message.refusal is not None: events_to_fire.append( build( RefusalDeltaEvent, type="refusal.delta", delta=choice.delta.refusal, snapshot=choice_snapshot.message.refusal, ) ) if choice.delta.tool_calls: tool_calls = choice_snapshot.message.tool_calls assert tool_calls is not None for tool_call_delta in choice.delta.tool_calls: tool_call = tool_calls[tool_call_delta.index] if tool_call.type == "function": assert tool_call_delta.function is not None events_to_fire.append( build( FunctionToolCallArgumentsDeltaEvent, type="tool_calls.function.arguments.delta", name=tool_call.function.name, index=tool_call_delta.index, arguments=tool_call.function.arguments, parsed_arguments=tool_call.function.parsed_arguments, arguments_delta=tool_call_delta.function.arguments or "", ) ) elif TYPE_CHECKING: # type: ignore[unreachable] assert_never(tool_call) if choice.logprobs is not None and choice_snapshot.logprobs is not None: if choice.logprobs.content and choice_snapshot.logprobs.content: events_to_fire.append( build( LogprobsContentDeltaEvent, type="logprobs.content.delta", content=choice.logprobs.content, snapshot=choice_snapshot.logprobs.content, ), ) if choice.logprobs.refusal and choice_snapshot.logprobs.refusal: events_to_fire.append( build( LogprobsRefusalDeltaEvent, type="logprobs.refusal.delta", refusal=choice.logprobs.refusal, snapshot=choice_snapshot.logprobs.refusal, ), ) events_to_fire.extend( choice_state.get_done_events( choice_chunk=choice, choice_snapshot=choice_snapshot, response_format=self._response_format, ) ) return events_to_fire class ChoiceEventState: def __init__(self, *, input_tools: list[ChatCompletionToolUnionParam]) -> None: self._input_tools = input_tools self._content_done = False self._refusal_done = False self._logprobs_content_done = False self._logprobs_refusal_done = False self._done_tool_calls: set[int] = set() self.__current_tool_call_index: int | None = None def get_done_events( self, *, choice_chunk: ChoiceChunk, choice_snapshot: ParsedChoiceSnapshot, response_format: type[ResponseFormatT] | ResponseFormatParam | Omit, ) -> list[ChatCompletionStreamEvent[ResponseFormatT]]: events_to_fire: list[ChatCompletionStreamEvent[ResponseFormatT]] = [] if choice_snapshot.finish_reason: events_to_fire.extend( self._content_done_events(choice_snapshot=choice_snapshot, response_format=response_format) ) if ( self.__current_tool_call_index is not None and self.__current_tool_call_index not in self._done_tool_calls ): self._add_tool_done_event( events_to_fire=events_to_fire, choice_snapshot=choice_snapshot, tool_index=self.__current_tool_call_index, ) for tool_call in choice_chunk.delta.tool_calls or []: if self.__current_tool_call_index != tool_call.index: events_to_fire.extend( self._content_done_events(choice_snapshot=choice_snapshot, response_format=response_format) ) if self.__current_tool_call_index is not None: self._add_tool_done_event( events_to_fire=events_to_fire, choice_snapshot=choice_snapshot, tool_index=self.__current_tool_call_index, ) self.__current_tool_call_index = tool_call.index return events_to_fire def _content_done_events( self, *, choice_snapshot: ParsedChoiceSnapshot, response_format: type[ResponseFormatT] | ResponseFormatParam | Omit, ) -> list[ChatCompletionStreamEvent[ResponseFormatT]]: events_to_fire: list[ChatCompletionStreamEvent[ResponseFormatT]] = [] if choice_snapshot.message.content and not self._content_done: self._content_done = True parsed = maybe_parse_content( response_format=response_format, message=choice_snapshot.message, ) # update the parsed content to now use the richer `response_format` # as opposed to the raw JSON-parsed object as the content is now # complete and can be fully validated. choice_snapshot.message.parsed = parsed events_to_fire.append( build( # we do this dance so that when the `ContentDoneEvent` instance # is printed at runtime the class name will include the solved # type variable, e.g. `ContentDoneEvent[MyModelType]` cast( # pyright: ignore[reportUnnecessaryCast] "type[ContentDoneEvent[ResponseFormatT]]", cast(Any, ContentDoneEvent), ), type="content.done", content=choice_snapshot.message.content, parsed=parsed, ), ) if choice_snapshot.message.refusal is not None and not self._refusal_done: self._refusal_done = True events_to_fire.append( build(RefusalDoneEvent, type="refusal.done", refusal=choice_snapshot.message.refusal), ) if ( choice_snapshot.logprobs is not None and choice_snapshot.logprobs.content is not None and not self._logprobs_content_done ): self._logprobs_content_done = True events_to_fire.append( build(LogprobsContentDoneEvent, type="logprobs.content.done", content=choice_snapshot.logprobs.content), ) if ( choice_snapshot.logprobs is not None and choice_snapshot.logprobs.refusal is not None and not self._logprobs_refusal_done ): self._logprobs_refusal_done = True events_to_fire.append( build(LogprobsRefusalDoneEvent, type="logprobs.refusal.done", refusal=choice_snapshot.logprobs.refusal), ) return events_to_fire def _add_tool_done_event( self, *, events_to_fire: list[ChatCompletionStreamEvent[ResponseFormatT]], choice_snapshot: ParsedChoiceSnapshot, tool_index: int, ) -> None: if tool_index in self._done_tool_calls: return self._done_tool_calls.add(tool_index) assert choice_snapshot.message.tool_calls is not None tool_call_snapshot = choice_snapshot.message.tool_calls[tool_index] if tool_call_snapshot.type == "function": parsed_arguments = parse_function_tool_arguments( input_tools=self._input_tools, function=tool_call_snapshot.function ) # update the parsed content to potentially use a richer type # as opposed to the raw JSON-parsed object as the content is now # complete and can be fully validated. tool_call_snapshot.function.parsed_arguments = parsed_arguments events_to_fire.append( build( FunctionToolCallArgumentsDoneEvent, type="tool_calls.function.arguments.done", index=tool_index, name=tool_call_snapshot.function.name, arguments=tool_call_snapshot.function.arguments, parsed_arguments=parsed_arguments, ) ) elif TYPE_CHECKING: # type: ignore[unreachable] assert_never(tool_call_snapshot) def _convert_initial_chunk_into_snapshot(chunk: ChatCompletionChunk) -> ParsedChatCompletionSnapshot: data = chunk.to_dict() choices = cast("list[object]", data["choices"]) for choice in chunk.choices: choices[choice.index] = { **choice.model_dump(exclude_unset=True, exclude={"delta"}), "message": choice.delta.to_dict(), } return cast( ParsedChatCompletionSnapshot, construct_type( type_=ParsedChatCompletionSnapshot, value={ "system_fingerprint": None, **data, "object": "chat.completion", }, ), ) def _is_valid_chat_completion_chunk_weak(sse_event: ChatCompletionChunk) -> bool: # Although the _raw_stream is always supposed to contain only objects adhering to ChatCompletionChunk schema, # this is broken by the Azure OpenAI in case of Asynchronous Filter enabled. # An easy filter is to check for the "object" property: # - should be "chat.completion.chunk" for a ChatCompletionChunk; # - is an empty string for Asynchronous Filter events. return sse_event.object == "chat.completion.chunk" # type: ignore # pylance reports this as a useless check ================================================ FILE: src/openai/lib/streaming/chat/_events.py ================================================ from typing import List, Union, Generic, Optional from typing_extensions import Literal from ._types import ParsedChatCompletionSnapshot from ...._models import BaseModel, GenericModel from ..._parsing import ResponseFormatT from ....types.chat import ChatCompletionChunk, ChatCompletionTokenLogprob class ChunkEvent(BaseModel): type: Literal["chunk"] chunk: ChatCompletionChunk snapshot: ParsedChatCompletionSnapshot class ContentDeltaEvent(BaseModel): """This event is yielded for every chunk with `choice.delta.content` data.""" type: Literal["content.delta"] delta: str snapshot: str parsed: Optional[object] = None class ContentDoneEvent(GenericModel, Generic[ResponseFormatT]): type: Literal["content.done"] content: str parsed: Optional[ResponseFormatT] = None class RefusalDeltaEvent(BaseModel): type: Literal["refusal.delta"] delta: str snapshot: str class RefusalDoneEvent(BaseModel): type: Literal["refusal.done"] refusal: str class FunctionToolCallArgumentsDeltaEvent(BaseModel): type: Literal["tool_calls.function.arguments.delta"] name: str index: int arguments: str """Accumulated raw JSON string""" parsed_arguments: object """The parsed arguments so far""" arguments_delta: str """The JSON string delta""" class FunctionToolCallArgumentsDoneEvent(BaseModel): type: Literal["tool_calls.function.arguments.done"] name: str index: int arguments: str """Accumulated raw JSON string""" parsed_arguments: object """The parsed arguments""" class LogprobsContentDeltaEvent(BaseModel): type: Literal["logprobs.content.delta"] content: List[ChatCompletionTokenLogprob] snapshot: List[ChatCompletionTokenLogprob] class LogprobsContentDoneEvent(BaseModel): type: Literal["logprobs.content.done"] content: List[ChatCompletionTokenLogprob] class LogprobsRefusalDeltaEvent(BaseModel): type: Literal["logprobs.refusal.delta"] refusal: List[ChatCompletionTokenLogprob] snapshot: List[ChatCompletionTokenLogprob] class LogprobsRefusalDoneEvent(BaseModel): type: Literal["logprobs.refusal.done"] refusal: List[ChatCompletionTokenLogprob] ChatCompletionStreamEvent = Union[ ChunkEvent, ContentDeltaEvent, ContentDoneEvent[ResponseFormatT], RefusalDeltaEvent, RefusalDoneEvent, FunctionToolCallArgumentsDeltaEvent, FunctionToolCallArgumentsDoneEvent, LogprobsContentDeltaEvent, LogprobsContentDoneEvent, LogprobsRefusalDeltaEvent, LogprobsRefusalDoneEvent, ] ================================================ FILE: src/openai/lib/streaming/chat/_types.py ================================================ from __future__ import annotations from typing_extensions import TypeAlias from ....types.chat import ParsedChoice, ParsedChatCompletion, ParsedChatCompletionMessage ParsedChatCompletionSnapshot: TypeAlias = ParsedChatCompletion[object] """Snapshot type representing an in-progress accumulation of a `ParsedChatCompletion` object. """ ParsedChatCompletionMessageSnapshot: TypeAlias = ParsedChatCompletionMessage[object] """Snapshot type representing an in-progress accumulation of a `ParsedChatCompletionMessage` object. If the content has been fully accumulated, the `.parsed` content will be the `response_format` instance, otherwise it'll be the raw JSON parsed version. """ ParsedChoiceSnapshot: TypeAlias = ParsedChoice[object] ================================================ FILE: src/openai/lib/streaming/responses/__init__.py ================================================ from ._events import ( ResponseTextDoneEvent as ResponseTextDoneEvent, ResponseTextDeltaEvent as ResponseTextDeltaEvent, ResponseFunctionCallArgumentsDeltaEvent as ResponseFunctionCallArgumentsDeltaEvent, ) from ._responses import ( ResponseStream as ResponseStream, AsyncResponseStream as AsyncResponseStream, ResponseStreamEvent as ResponseStreamEvent, ResponseStreamState as ResponseStreamState, ResponseStreamManager as ResponseStreamManager, AsyncResponseStreamManager as AsyncResponseStreamManager, ) ================================================ FILE: src/openai/lib/streaming/responses/_events.py ================================================ from __future__ import annotations from typing import Optional from typing_extensions import Union, Generic, TypeVar, Annotated, TypeAlias from ...._utils import PropertyInfo from ...._compat import GenericModel from ....types.responses import ( ParsedResponse, ResponseErrorEvent, ResponseFailedEvent, ResponseQueuedEvent, ResponseCreatedEvent, ResponseTextDoneEvent as RawResponseTextDoneEvent, ResponseAudioDoneEvent, ResponseCompletedEvent as RawResponseCompletedEvent, ResponseTextDeltaEvent as RawResponseTextDeltaEvent, ResponseAudioDeltaEvent, ResponseIncompleteEvent, ResponseInProgressEvent, ResponseRefusalDoneEvent, ResponseRefusalDeltaEvent, ResponseMcpCallFailedEvent, ResponseOutputItemDoneEvent, ResponseContentPartDoneEvent, ResponseOutputItemAddedEvent, ResponseContentPartAddedEvent, ResponseMcpCallCompletedEvent, ResponseMcpCallInProgressEvent, ResponseMcpListToolsFailedEvent, ResponseAudioTranscriptDoneEvent, ResponseAudioTranscriptDeltaEvent, ResponseMcpCallArgumentsDoneEvent, ResponseImageGenCallCompletedEvent, ResponseMcpCallArgumentsDeltaEvent, ResponseMcpListToolsCompletedEvent, ResponseImageGenCallGeneratingEvent, ResponseImageGenCallInProgressEvent, ResponseMcpListToolsInProgressEvent, ResponseWebSearchCallCompletedEvent, ResponseWebSearchCallSearchingEvent, ResponseCustomToolCallInputDoneEvent, ResponseFileSearchCallCompletedEvent, ResponseFileSearchCallSearchingEvent, ResponseWebSearchCallInProgressEvent, ResponseCustomToolCallInputDeltaEvent, ResponseFileSearchCallInProgressEvent, ResponseImageGenCallPartialImageEvent, ResponseReasoningSummaryPartDoneEvent, ResponseReasoningSummaryTextDoneEvent, ResponseFunctionCallArgumentsDoneEvent, ResponseOutputTextAnnotationAddedEvent, ResponseReasoningSummaryPartAddedEvent, ResponseReasoningSummaryTextDeltaEvent, ResponseFunctionCallArgumentsDeltaEvent as RawResponseFunctionCallArgumentsDeltaEvent, ResponseCodeInterpreterCallCodeDoneEvent, ResponseCodeInterpreterCallCodeDeltaEvent, ResponseCodeInterpreterCallCompletedEvent, ResponseCodeInterpreterCallInProgressEvent, ResponseCodeInterpreterCallInterpretingEvent, ) from ....types.responses.response_reasoning_text_done_event import ResponseReasoningTextDoneEvent from ....types.responses.response_reasoning_text_delta_event import ResponseReasoningTextDeltaEvent TextFormatT = TypeVar( "TextFormatT", # if it isn't given then we don't do any parsing default=None, ) class ResponseTextDeltaEvent(RawResponseTextDeltaEvent): snapshot: str class ResponseTextDoneEvent(RawResponseTextDoneEvent, GenericModel, Generic[TextFormatT]): parsed: Optional[TextFormatT] = None class ResponseFunctionCallArgumentsDeltaEvent(RawResponseFunctionCallArgumentsDeltaEvent): snapshot: str class ResponseCompletedEvent(RawResponseCompletedEvent, GenericModel, Generic[TextFormatT]): response: ParsedResponse[TextFormatT] # type: ignore[assignment] ResponseStreamEvent: TypeAlias = Annotated[ Union[ # wrappers with snapshots added on ResponseTextDeltaEvent, ResponseTextDoneEvent[TextFormatT], ResponseFunctionCallArgumentsDeltaEvent, ResponseCompletedEvent[TextFormatT], # the same as the non-accumulated API ResponseAudioDeltaEvent, ResponseAudioDoneEvent, ResponseAudioTranscriptDeltaEvent, ResponseAudioTranscriptDoneEvent, ResponseCodeInterpreterCallCodeDeltaEvent, ResponseCodeInterpreterCallCodeDoneEvent, ResponseCodeInterpreterCallCompletedEvent, ResponseCodeInterpreterCallInProgressEvent, ResponseCodeInterpreterCallInterpretingEvent, ResponseContentPartAddedEvent, ResponseContentPartDoneEvent, ResponseCreatedEvent, ResponseErrorEvent, ResponseFileSearchCallCompletedEvent, ResponseFileSearchCallInProgressEvent, ResponseFileSearchCallSearchingEvent, ResponseFunctionCallArgumentsDoneEvent, ResponseInProgressEvent, ResponseFailedEvent, ResponseIncompleteEvent, ResponseOutputItemAddedEvent, ResponseOutputItemDoneEvent, ResponseRefusalDeltaEvent, ResponseRefusalDoneEvent, ResponseTextDoneEvent, ResponseWebSearchCallCompletedEvent, ResponseWebSearchCallInProgressEvent, ResponseWebSearchCallSearchingEvent, ResponseReasoningSummaryPartAddedEvent, ResponseReasoningSummaryPartDoneEvent, ResponseReasoningSummaryTextDeltaEvent, ResponseReasoningSummaryTextDoneEvent, ResponseImageGenCallCompletedEvent, ResponseImageGenCallInProgressEvent, ResponseImageGenCallGeneratingEvent, ResponseImageGenCallPartialImageEvent, ResponseMcpCallCompletedEvent, ResponseMcpCallArgumentsDeltaEvent, ResponseMcpCallArgumentsDoneEvent, ResponseMcpCallFailedEvent, ResponseMcpCallInProgressEvent, ResponseMcpListToolsCompletedEvent, ResponseMcpListToolsFailedEvent, ResponseMcpListToolsInProgressEvent, ResponseOutputTextAnnotationAddedEvent, ResponseQueuedEvent, ResponseReasoningTextDeltaEvent, ResponseReasoningTextDoneEvent, ResponseCustomToolCallInputDeltaEvent, ResponseCustomToolCallInputDoneEvent, ], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/lib/streaming/responses/_responses.py ================================================ from __future__ import annotations import inspect from types import TracebackType from typing import Any, List, Generic, Iterable, Awaitable, cast from typing_extensions import Self, Callable, Iterator, AsyncIterator from ._types import ParsedResponseSnapshot from ._events import ( ResponseStreamEvent, ResponseTextDoneEvent, ResponseCompletedEvent, ResponseTextDeltaEvent, ResponseFunctionCallArgumentsDeltaEvent, ) from ...._types import Omit, omit from ...._utils import is_given, consume_sync_iterator, consume_async_iterator from ...._models import build, construct_type_unchecked from ...._streaming import Stream, AsyncStream from ....types.responses import ParsedResponse, ResponseStreamEvent as RawResponseStreamEvent from ..._parsing._responses import TextFormatT, parse_text, parse_response from ....types.responses.tool_param import ToolParam from ....types.responses.parsed_response import ( ParsedContent, ParsedResponseOutputMessage, ParsedResponseFunctionToolCall, ) class ResponseStream(Generic[TextFormatT]): def __init__( self, *, raw_stream: Stream[RawResponseStreamEvent], text_format: type[TextFormatT] | Omit, input_tools: Iterable[ToolParam] | Omit, starting_after: int | None, ) -> None: self._raw_stream = raw_stream self._response = raw_stream.response self._iterator = self.__stream__() self._state = ResponseStreamState(text_format=text_format, input_tools=input_tools) self._starting_after = starting_after def __next__(self) -> ResponseStreamEvent[TextFormatT]: return self._iterator.__next__() def __iter__(self) -> Iterator[ResponseStreamEvent[TextFormatT]]: for item in self._iterator: yield item def __enter__(self) -> Self: return self def __stream__(self) -> Iterator[ResponseStreamEvent[TextFormatT]]: for sse_event in self._raw_stream: events_to_fire = self._state.handle_event(sse_event) for event in events_to_fire: if self._starting_after is None or event.sequence_number > self._starting_after: yield event def __exit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None, ) -> None: self.close() def close(self) -> None: """ Close the response and release the connection. Automatically called if the response body is read to completion. """ self._response.close() def get_final_response(self) -> ParsedResponse[TextFormatT]: """Waits until the stream has been read to completion and returns the accumulated `ParsedResponse` object. """ self.until_done() response = self._state._completed_response if not response: raise RuntimeError("Didn't receive a `response.completed` event.") return response def until_done(self) -> Self: """Blocks until the stream has been consumed.""" consume_sync_iterator(self) return self class ResponseStreamManager(Generic[TextFormatT]): def __init__( self, api_request: Callable[[], Stream[RawResponseStreamEvent]], *, text_format: type[TextFormatT] | Omit, input_tools: Iterable[ToolParam] | Omit, starting_after: int | None, ) -> None: self.__stream: ResponseStream[TextFormatT] | None = None self.__api_request = api_request self.__text_format = text_format self.__input_tools = input_tools self.__starting_after = starting_after def __enter__(self) -> ResponseStream[TextFormatT]: raw_stream = self.__api_request() self.__stream = ResponseStream( raw_stream=raw_stream, text_format=self.__text_format, input_tools=self.__input_tools, starting_after=self.__starting_after, ) return self.__stream def __exit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None, ) -> None: if self.__stream is not None: self.__stream.close() class AsyncResponseStream(Generic[TextFormatT]): def __init__( self, *, raw_stream: AsyncStream[RawResponseStreamEvent], text_format: type[TextFormatT] | Omit, input_tools: Iterable[ToolParam] | Omit, starting_after: int | None, ) -> None: self._raw_stream = raw_stream self._response = raw_stream.response self._iterator = self.__stream__() self._state = ResponseStreamState(text_format=text_format, input_tools=input_tools) self._starting_after = starting_after async def __anext__(self) -> ResponseStreamEvent[TextFormatT]: return await self._iterator.__anext__() async def __aiter__(self) -> AsyncIterator[ResponseStreamEvent[TextFormatT]]: async for item in self._iterator: yield item async def __stream__(self) -> AsyncIterator[ResponseStreamEvent[TextFormatT]]: async for sse_event in self._raw_stream: events_to_fire = self._state.handle_event(sse_event) for event in events_to_fire: if self._starting_after is None or event.sequence_number > self._starting_after: yield event async def __aenter__(self) -> Self: return self async def __aexit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None, ) -> None: await self.close() async def close(self) -> None: """ Close the response and release the connection. Automatically called if the response body is read to completion. """ await self._response.aclose() async def get_final_response(self) -> ParsedResponse[TextFormatT]: """Waits until the stream has been read to completion and returns the accumulated `ParsedResponse` object. """ await self.until_done() response = self._state._completed_response if not response: raise RuntimeError("Didn't receive a `response.completed` event.") return response async def until_done(self) -> Self: """Blocks until the stream has been consumed.""" await consume_async_iterator(self) return self class AsyncResponseStreamManager(Generic[TextFormatT]): def __init__( self, api_request: Awaitable[AsyncStream[RawResponseStreamEvent]], *, text_format: type[TextFormatT] | Omit, input_tools: Iterable[ToolParam] | Omit, starting_after: int | None, ) -> None: self.__stream: AsyncResponseStream[TextFormatT] | None = None self.__api_request = api_request self.__text_format = text_format self.__input_tools = input_tools self.__starting_after = starting_after async def __aenter__(self) -> AsyncResponseStream[TextFormatT]: raw_stream = await self.__api_request self.__stream = AsyncResponseStream( raw_stream=raw_stream, text_format=self.__text_format, input_tools=self.__input_tools, starting_after=self.__starting_after, ) return self.__stream async def __aexit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None, ) -> None: if self.__stream is not None: await self.__stream.close() class ResponseStreamState(Generic[TextFormatT]): def __init__( self, *, input_tools: Iterable[ToolParam] | Omit, text_format: type[TextFormatT] | Omit, ) -> None: self.__current_snapshot: ParsedResponseSnapshot | None = None self._completed_response: ParsedResponse[TextFormatT] | None = None self._input_tools = [tool for tool in input_tools] if is_given(input_tools) else [] self._text_format = text_format self._rich_text_format: type | Omit = text_format if inspect.isclass(text_format) else omit def handle_event(self, event: RawResponseStreamEvent) -> List[ResponseStreamEvent[TextFormatT]]: self.__current_snapshot = snapshot = self.accumulate_event(event) events: List[ResponseStreamEvent[TextFormatT]] = [] if event.type == "response.output_text.delta": output = snapshot.output[event.output_index] assert output.type == "message" content = output.content[event.content_index] assert content.type == "output_text" events.append( build( ResponseTextDeltaEvent, content_index=event.content_index, delta=event.delta, item_id=event.item_id, output_index=event.output_index, sequence_number=event.sequence_number, logprobs=event.logprobs, type="response.output_text.delta", snapshot=content.text, ) ) elif event.type == "response.output_text.done": output = snapshot.output[event.output_index] assert output.type == "message" content = output.content[event.content_index] assert content.type == "output_text" events.append( build( ResponseTextDoneEvent[TextFormatT], content_index=event.content_index, item_id=event.item_id, output_index=event.output_index, sequence_number=event.sequence_number, logprobs=event.logprobs, type="response.output_text.done", text=event.text, parsed=parse_text(event.text, text_format=self._text_format), ) ) elif event.type == "response.function_call_arguments.delta": output = snapshot.output[event.output_index] assert output.type == "function_call" events.append( build( ResponseFunctionCallArgumentsDeltaEvent, delta=event.delta, item_id=event.item_id, output_index=event.output_index, sequence_number=event.sequence_number, type="response.function_call_arguments.delta", snapshot=output.arguments, ) ) elif event.type == "response.completed": response = self._completed_response assert response is not None events.append( build( ResponseCompletedEvent, sequence_number=event.sequence_number, type="response.completed", response=response, ) ) else: events.append(event) return events def accumulate_event(self, event: RawResponseStreamEvent) -> ParsedResponseSnapshot: snapshot = self.__current_snapshot if snapshot is None: return self._create_initial_response(event) if event.type == "response.output_item.added": if event.item.type == "function_call": snapshot.output.append( construct_type_unchecked( type_=cast(Any, ParsedResponseFunctionToolCall), value=event.item.to_dict() ) ) elif event.item.type == "message": snapshot.output.append( construct_type_unchecked(type_=cast(Any, ParsedResponseOutputMessage), value=event.item.to_dict()) ) else: snapshot.output.append(event.item) elif event.type == "response.content_part.added": output = snapshot.output[event.output_index] if output.type == "message": output.content.append( construct_type_unchecked(type_=cast(Any, ParsedContent), value=event.part.to_dict()) ) elif event.type == "response.output_text.delta": output = snapshot.output[event.output_index] if output.type == "message": content = output.content[event.content_index] assert content.type == "output_text" content.text += event.delta elif event.type == "response.function_call_arguments.delta": output = snapshot.output[event.output_index] if output.type == "function_call": output.arguments += event.delta elif event.type == "response.completed": self._completed_response = parse_response( text_format=self._text_format, response=event.response, input_tools=self._input_tools, ) return snapshot def _create_initial_response(self, event: RawResponseStreamEvent) -> ParsedResponseSnapshot: if event.type != "response.created": raise RuntimeError(f"Expected to have received `response.created` before `{event.type}`") return construct_type_unchecked(type_=ParsedResponseSnapshot, value=event.response.to_dict()) ================================================ FILE: src/openai/lib/streaming/responses/_types.py ================================================ from __future__ import annotations from typing_extensions import TypeAlias from ....types.responses import ParsedResponse ParsedResponseSnapshot: TypeAlias = ParsedResponse[object] """Snapshot type representing an in-progress accumulation of a `ParsedResponse` object. """ ================================================ FILE: src/openai/pagination.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Any, List, Generic, TypeVar, Optional, cast from typing_extensions import Protocol, override, runtime_checkable from ._base_client import BasePage, PageInfo, BaseSyncPage, BaseAsyncPage __all__ = [ "SyncPage", "AsyncPage", "SyncCursorPage", "AsyncCursorPage", "SyncConversationCursorPage", "AsyncConversationCursorPage", ] _T = TypeVar("_T") @runtime_checkable class CursorPageItem(Protocol): id: Optional[str] class SyncPage(BaseSyncPage[_T], BasePage[_T], Generic[_T]): """Note: no pagination actually occurs yet, this is for forwards-compatibility.""" data: List[_T] object: str @override def _get_page_items(self) -> List[_T]: data = self.data if not data: return [] return data @override def next_page_info(self) -> None: """ This page represents a response that isn't actually paginated at the API level so there will never be a next page. """ return None class AsyncPage(BaseAsyncPage[_T], BasePage[_T], Generic[_T]): """Note: no pagination actually occurs yet, this is for forwards-compatibility.""" data: List[_T] object: str @override def _get_page_items(self) -> List[_T]: data = self.data if not data: return [] return data @override def next_page_info(self) -> None: """ This page represents a response that isn't actually paginated at the API level so there will never be a next page. """ return None class SyncCursorPage(BaseSyncPage[_T], BasePage[_T], Generic[_T]): data: List[_T] has_more: Optional[bool] = None @override def _get_page_items(self) -> List[_T]: data = self.data if not data: return [] return data @override def has_next_page(self) -> bool: has_more = self.has_more if has_more is not None and has_more is False: return False return super().has_next_page() @override def next_page_info(self) -> Optional[PageInfo]: data = self.data if not data: return None item = cast(Any, data[-1]) if not isinstance(item, CursorPageItem) or item.id is None: # TODO emit warning log return None return PageInfo(params={"after": item.id}) class AsyncCursorPage(BaseAsyncPage[_T], BasePage[_T], Generic[_T]): data: List[_T] has_more: Optional[bool] = None @override def _get_page_items(self) -> List[_T]: data = self.data if not data: return [] return data @override def has_next_page(self) -> bool: has_more = self.has_more if has_more is not None and has_more is False: return False return super().has_next_page() @override def next_page_info(self) -> Optional[PageInfo]: data = self.data if not data: return None item = cast(Any, data[-1]) if not isinstance(item, CursorPageItem) or item.id is None: # TODO emit warning log return None return PageInfo(params={"after": item.id}) class SyncConversationCursorPage(BaseSyncPage[_T], BasePage[_T], Generic[_T]): data: List[_T] has_more: Optional[bool] = None last_id: Optional[str] = None @override def _get_page_items(self) -> List[_T]: data = self.data if not data: return [] return data @override def has_next_page(self) -> bool: has_more = self.has_more if has_more is not None and has_more is False: return False return super().has_next_page() @override def next_page_info(self) -> Optional[PageInfo]: last_id = self.last_id if not last_id: return None return PageInfo(params={"after": last_id}) class AsyncConversationCursorPage(BaseAsyncPage[_T], BasePage[_T], Generic[_T]): data: List[_T] has_more: Optional[bool] = None last_id: Optional[str] = None @override def _get_page_items(self) -> List[_T]: data = self.data if not data: return [] return data @override def has_next_page(self) -> bool: has_more = self.has_more if has_more is not None and has_more is False: return False return super().has_next_page() @override def next_page_info(self) -> Optional[PageInfo]: last_id = self.last_id if not last_id: return None return PageInfo(params={"after": last_id}) ================================================ FILE: src/openai/py.typed ================================================ ================================================ FILE: src/openai/resources/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .beta import ( Beta, AsyncBeta, BetaWithRawResponse, AsyncBetaWithRawResponse, BetaWithStreamingResponse, AsyncBetaWithStreamingResponse, ) from .chat import ( Chat, AsyncChat, ChatWithRawResponse, AsyncChatWithRawResponse, ChatWithStreamingResponse, AsyncChatWithStreamingResponse, ) from .audio import ( Audio, AsyncAudio, AudioWithRawResponse, AsyncAudioWithRawResponse, AudioWithStreamingResponse, AsyncAudioWithStreamingResponse, ) from .evals import ( Evals, AsyncEvals, EvalsWithRawResponse, AsyncEvalsWithRawResponse, EvalsWithStreamingResponse, AsyncEvalsWithStreamingResponse, ) from .files import ( Files, AsyncFiles, FilesWithRawResponse, AsyncFilesWithRawResponse, FilesWithStreamingResponse, AsyncFilesWithStreamingResponse, ) from .images import ( Images, AsyncImages, ImagesWithRawResponse, AsyncImagesWithRawResponse, ImagesWithStreamingResponse, AsyncImagesWithStreamingResponse, ) from .models import ( Models, AsyncModels, ModelsWithRawResponse, AsyncModelsWithRawResponse, ModelsWithStreamingResponse, AsyncModelsWithStreamingResponse, ) from .skills import ( Skills, AsyncSkills, SkillsWithRawResponse, AsyncSkillsWithRawResponse, SkillsWithStreamingResponse, AsyncSkillsWithStreamingResponse, ) from .videos import ( Videos, AsyncVideos, VideosWithRawResponse, AsyncVideosWithRawResponse, VideosWithStreamingResponse, AsyncVideosWithStreamingResponse, ) from .batches import ( Batches, AsyncBatches, BatchesWithRawResponse, AsyncBatchesWithRawResponse, BatchesWithStreamingResponse, AsyncBatchesWithStreamingResponse, ) from .uploads import ( Uploads, AsyncUploads, UploadsWithRawResponse, AsyncUploadsWithRawResponse, UploadsWithStreamingResponse, AsyncUploadsWithStreamingResponse, ) from .containers import ( Containers, AsyncContainers, ContainersWithRawResponse, AsyncContainersWithRawResponse, ContainersWithStreamingResponse, AsyncContainersWithStreamingResponse, ) from .embeddings import ( Embeddings, AsyncEmbeddings, EmbeddingsWithRawResponse, AsyncEmbeddingsWithRawResponse, EmbeddingsWithStreamingResponse, AsyncEmbeddingsWithStreamingResponse, ) from .completions import ( Completions, AsyncCompletions, CompletionsWithRawResponse, AsyncCompletionsWithRawResponse, CompletionsWithStreamingResponse, AsyncCompletionsWithStreamingResponse, ) from .fine_tuning import ( FineTuning, AsyncFineTuning, FineTuningWithRawResponse, AsyncFineTuningWithRawResponse, FineTuningWithStreamingResponse, AsyncFineTuningWithStreamingResponse, ) from .moderations import ( Moderations, AsyncModerations, ModerationsWithRawResponse, AsyncModerationsWithRawResponse, ModerationsWithStreamingResponse, AsyncModerationsWithStreamingResponse, ) from .vector_stores import ( VectorStores, AsyncVectorStores, VectorStoresWithRawResponse, AsyncVectorStoresWithRawResponse, VectorStoresWithStreamingResponse, AsyncVectorStoresWithStreamingResponse, ) __all__ = [ "Completions", "AsyncCompletions", "CompletionsWithRawResponse", "AsyncCompletionsWithRawResponse", "CompletionsWithStreamingResponse", "AsyncCompletionsWithStreamingResponse", "Chat", "AsyncChat", "ChatWithRawResponse", "AsyncChatWithRawResponse", "ChatWithStreamingResponse", "AsyncChatWithStreamingResponse", "Embeddings", "AsyncEmbeddings", "EmbeddingsWithRawResponse", "AsyncEmbeddingsWithRawResponse", "EmbeddingsWithStreamingResponse", "AsyncEmbeddingsWithStreamingResponse", "Files", "AsyncFiles", "FilesWithRawResponse", "AsyncFilesWithRawResponse", "FilesWithStreamingResponse", "AsyncFilesWithStreamingResponse", "Images", "AsyncImages", "ImagesWithRawResponse", "AsyncImagesWithRawResponse", "ImagesWithStreamingResponse", "AsyncImagesWithStreamingResponse", "Audio", "AsyncAudio", "AudioWithRawResponse", "AsyncAudioWithRawResponse", "AudioWithStreamingResponse", "AsyncAudioWithStreamingResponse", "Moderations", "AsyncModerations", "ModerationsWithRawResponse", "AsyncModerationsWithRawResponse", "ModerationsWithStreamingResponse", "AsyncModerationsWithStreamingResponse", "Models", "AsyncModels", "ModelsWithRawResponse", "AsyncModelsWithRawResponse", "ModelsWithStreamingResponse", "AsyncModelsWithStreamingResponse", "FineTuning", "AsyncFineTuning", "FineTuningWithRawResponse", "AsyncFineTuningWithRawResponse", "FineTuningWithStreamingResponse", "AsyncFineTuningWithStreamingResponse", "VectorStores", "AsyncVectorStores", "VectorStoresWithRawResponse", "AsyncVectorStoresWithRawResponse", "VectorStoresWithStreamingResponse", "AsyncVectorStoresWithStreamingResponse", "Beta", "AsyncBeta", "BetaWithRawResponse", "AsyncBetaWithRawResponse", "BetaWithStreamingResponse", "AsyncBetaWithStreamingResponse", "Batches", "AsyncBatches", "BatchesWithRawResponse", "AsyncBatchesWithRawResponse", "BatchesWithStreamingResponse", "AsyncBatchesWithStreamingResponse", "Uploads", "AsyncUploads", "UploadsWithRawResponse", "AsyncUploadsWithRawResponse", "UploadsWithStreamingResponse", "AsyncUploadsWithStreamingResponse", "Evals", "AsyncEvals", "EvalsWithRawResponse", "AsyncEvalsWithRawResponse", "EvalsWithStreamingResponse", "AsyncEvalsWithStreamingResponse", "Containers", "AsyncContainers", "ContainersWithRawResponse", "AsyncContainersWithRawResponse", "ContainersWithStreamingResponse", "AsyncContainersWithStreamingResponse", "Skills", "AsyncSkills", "SkillsWithRawResponse", "AsyncSkillsWithRawResponse", "SkillsWithStreamingResponse", "AsyncSkillsWithStreamingResponse", "Videos", "AsyncVideos", "VideosWithRawResponse", "AsyncVideosWithRawResponse", "VideosWithStreamingResponse", "AsyncVideosWithStreamingResponse", ] ================================================ FILE: src/openai/resources/audio/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .audio import ( Audio, AsyncAudio, AudioWithRawResponse, AsyncAudioWithRawResponse, AudioWithStreamingResponse, AsyncAudioWithStreamingResponse, ) from .speech import ( Speech, AsyncSpeech, SpeechWithRawResponse, AsyncSpeechWithRawResponse, SpeechWithStreamingResponse, AsyncSpeechWithStreamingResponse, ) from .translations import ( Translations, AsyncTranslations, TranslationsWithRawResponse, AsyncTranslationsWithRawResponse, TranslationsWithStreamingResponse, AsyncTranslationsWithStreamingResponse, ) from .transcriptions import ( Transcriptions, AsyncTranscriptions, TranscriptionsWithRawResponse, AsyncTranscriptionsWithRawResponse, TranscriptionsWithStreamingResponse, AsyncTranscriptionsWithStreamingResponse, ) __all__ = [ "Transcriptions", "AsyncTranscriptions", "TranscriptionsWithRawResponse", "AsyncTranscriptionsWithRawResponse", "TranscriptionsWithStreamingResponse", "AsyncTranscriptionsWithStreamingResponse", "Translations", "AsyncTranslations", "TranslationsWithRawResponse", "AsyncTranslationsWithRawResponse", "TranslationsWithStreamingResponse", "AsyncTranslationsWithStreamingResponse", "Speech", "AsyncSpeech", "SpeechWithRawResponse", "AsyncSpeechWithRawResponse", "SpeechWithStreamingResponse", "AsyncSpeechWithStreamingResponse", "Audio", "AsyncAudio", "AudioWithRawResponse", "AsyncAudioWithRawResponse", "AudioWithStreamingResponse", "AsyncAudioWithStreamingResponse", ] ================================================ FILE: src/openai/resources/audio/audio.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .speech import ( Speech, AsyncSpeech, SpeechWithRawResponse, AsyncSpeechWithRawResponse, SpeechWithStreamingResponse, AsyncSpeechWithStreamingResponse, ) from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from .translations import ( Translations, AsyncTranslations, TranslationsWithRawResponse, AsyncTranslationsWithRawResponse, TranslationsWithStreamingResponse, AsyncTranslationsWithStreamingResponse, ) from .transcriptions import ( Transcriptions, AsyncTranscriptions, TranscriptionsWithRawResponse, AsyncTranscriptionsWithRawResponse, TranscriptionsWithStreamingResponse, AsyncTranscriptionsWithStreamingResponse, ) __all__ = ["Audio", "AsyncAudio"] class Audio(SyncAPIResource): @cached_property def transcriptions(self) -> Transcriptions: """Turn audio into text or text into audio.""" return Transcriptions(self._client) @cached_property def translations(self) -> Translations: """Turn audio into text or text into audio.""" return Translations(self._client) @cached_property def speech(self) -> Speech: """Turn audio into text or text into audio.""" return Speech(self._client) @cached_property def with_raw_response(self) -> AudioWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AudioWithRawResponse(self) @cached_property def with_streaming_response(self) -> AudioWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AudioWithStreamingResponse(self) class AsyncAudio(AsyncAPIResource): @cached_property def transcriptions(self) -> AsyncTranscriptions: """Turn audio into text or text into audio.""" return AsyncTranscriptions(self._client) @cached_property def translations(self) -> AsyncTranslations: """Turn audio into text or text into audio.""" return AsyncTranslations(self._client) @cached_property def speech(self) -> AsyncSpeech: """Turn audio into text or text into audio.""" return AsyncSpeech(self._client) @cached_property def with_raw_response(self) -> AsyncAudioWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncAudioWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncAudioWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncAudioWithStreamingResponse(self) class AudioWithRawResponse: def __init__(self, audio: Audio) -> None: self._audio = audio @cached_property def transcriptions(self) -> TranscriptionsWithRawResponse: """Turn audio into text or text into audio.""" return TranscriptionsWithRawResponse(self._audio.transcriptions) @cached_property def translations(self) -> TranslationsWithRawResponse: """Turn audio into text or text into audio.""" return TranslationsWithRawResponse(self._audio.translations) @cached_property def speech(self) -> SpeechWithRawResponse: """Turn audio into text or text into audio.""" return SpeechWithRawResponse(self._audio.speech) class AsyncAudioWithRawResponse: def __init__(self, audio: AsyncAudio) -> None: self._audio = audio @cached_property def transcriptions(self) -> AsyncTranscriptionsWithRawResponse: """Turn audio into text or text into audio.""" return AsyncTranscriptionsWithRawResponse(self._audio.transcriptions) @cached_property def translations(self) -> AsyncTranslationsWithRawResponse: """Turn audio into text or text into audio.""" return AsyncTranslationsWithRawResponse(self._audio.translations) @cached_property def speech(self) -> AsyncSpeechWithRawResponse: """Turn audio into text or text into audio.""" return AsyncSpeechWithRawResponse(self._audio.speech) class AudioWithStreamingResponse: def __init__(self, audio: Audio) -> None: self._audio = audio @cached_property def transcriptions(self) -> TranscriptionsWithStreamingResponse: """Turn audio into text or text into audio.""" return TranscriptionsWithStreamingResponse(self._audio.transcriptions) @cached_property def translations(self) -> TranslationsWithStreamingResponse: """Turn audio into text or text into audio.""" return TranslationsWithStreamingResponse(self._audio.translations) @cached_property def speech(self) -> SpeechWithStreamingResponse: """Turn audio into text or text into audio.""" return SpeechWithStreamingResponse(self._audio.speech) class AsyncAudioWithStreamingResponse: def __init__(self, audio: AsyncAudio) -> None: self._audio = audio @cached_property def transcriptions(self) -> AsyncTranscriptionsWithStreamingResponse: """Turn audio into text or text into audio.""" return AsyncTranscriptionsWithStreamingResponse(self._audio.transcriptions) @cached_property def translations(self) -> AsyncTranslationsWithStreamingResponse: """Turn audio into text or text into audio.""" return AsyncTranslationsWithStreamingResponse(self._audio.translations) @cached_property def speech(self) -> AsyncSpeechWithStreamingResponse: """Turn audio into text or text into audio.""" return AsyncSpeechWithStreamingResponse(self._audio.speech) ================================================ FILE: src/openai/resources/audio/speech.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal import httpx from ... import _legacy_response from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( StreamedBinaryAPIResponse, AsyncStreamedBinaryAPIResponse, to_custom_streamed_response_wrapper, async_to_custom_streamed_response_wrapper, ) from ...types.audio import speech_create_params from ..._base_client import make_request_options from ...types.audio.speech_model import SpeechModel __all__ = ["Speech", "AsyncSpeech"] class Speech(SyncAPIResource): """Turn audio into text or text into audio.""" @cached_property def with_raw_response(self) -> SpeechWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return SpeechWithRawResponse(self) @cached_property def with_streaming_response(self) -> SpeechWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return SpeechWithStreamingResponse(self) def create( self, *, input: str, model: Union[str, SpeechModel], voice: speech_create_params.Voice, instructions: str | Omit = omit, response_format: Literal["mp3", "opus", "aac", "flac", "wav", "pcm"] | Omit = omit, speed: float | Omit = omit, stream_format: Literal["sse", "audio"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: """ Generates audio from the input text. Returns the audio file content, or a stream of audio events. Args: input: The text to generate audio for. The maximum length is 4096 characters. model: One of the available [TTS models](https://platform.openai.com/docs/models#tts): `tts-1`, `tts-1-hd`, `gpt-4o-mini-tts`, or `gpt-4o-mini-tts-2025-12-15`. voice: The voice to use when generating the audio. Supported built-in voices are `alloy`, `ash`, `ballad`, `coral`, `echo`, `fable`, `onyx`, `nova`, `sage`, `shimmer`, `verse`, `marin`, and `cedar`. You may also provide a custom voice object with an `id`, for example `{ "id": "voice_1234" }`. Previews of the voices are available in the [Text to speech guide](https://platform.openai.com/docs/guides/text-to-speech#voice-options). instructions: Control the voice of your generated audio with additional instructions. Does not work with `tts-1` or `tts-1-hd`. response_format: The format to audio in. Supported formats are `mp3`, `opus`, `aac`, `flac`, `wav`, and `pcm`. speed: The speed of the generated audio. Select a value from `0.25` to `4.0`. `1.0` is the default. stream_format: The format to stream the audio in. Supported formats are `sse` and `audio`. `sse` is not supported for `tts-1` or `tts-1-hd`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})} return self._post( "/audio/speech", body=maybe_transform( { "input": input, "model": model, "voice": voice, "instructions": instructions, "response_format": response_format, "speed": speed, "stream_format": stream_format, }, speech_create_params.SpeechCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=_legacy_response.HttpxBinaryResponseContent, ) class AsyncSpeech(AsyncAPIResource): """Turn audio into text or text into audio.""" @cached_property def with_raw_response(self) -> AsyncSpeechWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncSpeechWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncSpeechWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncSpeechWithStreamingResponse(self) async def create( self, *, input: str, model: Union[str, SpeechModel], voice: speech_create_params.Voice, instructions: str | Omit = omit, response_format: Literal["mp3", "opus", "aac", "flac", "wav", "pcm"] | Omit = omit, speed: float | Omit = omit, stream_format: Literal["sse", "audio"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: """ Generates audio from the input text. Returns the audio file content, or a stream of audio events. Args: input: The text to generate audio for. The maximum length is 4096 characters. model: One of the available [TTS models](https://platform.openai.com/docs/models#tts): `tts-1`, `tts-1-hd`, `gpt-4o-mini-tts`, or `gpt-4o-mini-tts-2025-12-15`. voice: The voice to use when generating the audio. Supported built-in voices are `alloy`, `ash`, `ballad`, `coral`, `echo`, `fable`, `onyx`, `nova`, `sage`, `shimmer`, `verse`, `marin`, and `cedar`. You may also provide a custom voice object with an `id`, for example `{ "id": "voice_1234" }`. Previews of the voices are available in the [Text to speech guide](https://platform.openai.com/docs/guides/text-to-speech#voice-options). instructions: Control the voice of your generated audio with additional instructions. Does not work with `tts-1` or `tts-1-hd`. response_format: The format to audio in. Supported formats are `mp3`, `opus`, `aac`, `flac`, `wav`, and `pcm`. speed: The speed of the generated audio. Select a value from `0.25` to `4.0`. `1.0` is the default. stream_format: The format to stream the audio in. Supported formats are `sse` and `audio`. `sse` is not supported for `tts-1` or `tts-1-hd`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})} return await self._post( "/audio/speech", body=await async_maybe_transform( { "input": input, "model": model, "voice": voice, "instructions": instructions, "response_format": response_format, "speed": speed, "stream_format": stream_format, }, speech_create_params.SpeechCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=_legacy_response.HttpxBinaryResponseContent, ) class SpeechWithRawResponse: def __init__(self, speech: Speech) -> None: self._speech = speech self.create = _legacy_response.to_raw_response_wrapper( speech.create, ) class AsyncSpeechWithRawResponse: def __init__(self, speech: AsyncSpeech) -> None: self._speech = speech self.create = _legacy_response.async_to_raw_response_wrapper( speech.create, ) class SpeechWithStreamingResponse: def __init__(self, speech: Speech) -> None: self._speech = speech self.create = to_custom_streamed_response_wrapper( speech.create, StreamedBinaryAPIResponse, ) class AsyncSpeechWithStreamingResponse: def __init__(self, speech: AsyncSpeech) -> None: self._speech = speech self.create = async_to_custom_streamed_response_wrapper( speech.create, AsyncStreamedBinaryAPIResponse, ) ================================================ FILE: src/openai/resources/audio/transcriptions.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import logging from typing import TYPE_CHECKING, List, Union, Mapping, Optional, cast from typing_extensions import Literal, overload, assert_never import httpx from ... import _legacy_response from ..._types import ( Body, Omit, Query, Headers, NotGiven, FileTypes, SequenceNotStr, omit, not_given, ) from ..._utils import extract_files, required_args, maybe_transform, deepcopy_minimal, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ..._streaming import Stream, AsyncStream from ...types.audio import transcription_create_params from ..._base_client import make_request_options from ...types.audio_model import AudioModel from ...types.audio.transcription import Transcription from ...types.audio_response_format import AudioResponseFormat from ...types.audio.transcription_include import TranscriptionInclude from ...types.audio.transcription_verbose import TranscriptionVerbose from ...types.audio.transcription_diarized import TranscriptionDiarized from ...types.audio.transcription_stream_event import TranscriptionStreamEvent from ...types.audio.transcription_create_response import TranscriptionCreateResponse __all__ = ["Transcriptions", "AsyncTranscriptions"] log: logging.Logger = logging.getLogger("openai.audio.transcriptions") class Transcriptions(SyncAPIResource): """Turn audio into text or text into audio.""" @cached_property def with_raw_response(self) -> TranscriptionsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return TranscriptionsWithRawResponse(self) @cached_property def with_streaming_response(self) -> TranscriptionsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return TranscriptionsWithStreamingResponse(self) @overload def create( self, *, file: FileTypes, model: Union[str, AudioModel], chunking_strategy: Optional[transcription_create_params.ChunkingStrategy] | Omit = omit, include: List[TranscriptionInclude] | Omit = omit, language: str | Omit = omit, prompt: str | Omit = omit, response_format: Union[Literal["json"], Omit] = omit, stream: Optional[Literal[False]] | Omit = omit, temperature: float | Omit = omit, timestamp_granularities: List[Literal["word", "segment"]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Transcription: """ Transcribes audio into the input language. Returns a transcription object in `json`, `diarized_json`, or `verbose_json` format, or a stream of transcript events. Args: file: The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm. model: ID of the model to use. The options are `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `whisper-1` (which is powered by our open source Whisper V2 model), and `gpt-4o-transcribe-diarize`. chunking_strategy: Controls how the audio is cut into chunks. When set to `"auto"`, the server first normalizes loudness and then uses voice activity detection (VAD) to choose boundaries. `server_vad` object can be provided to tweak VAD detection parameters manually. If unset, the audio is transcribed as a single block. include: Additional information to include in the transcription response. `logprobs` will return the log probabilities of the tokens in the response to understand the model's confidence in the transcription. `logprobs` only works with response_format set to `json` and only with the models `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, and `gpt-4o-mini-transcribe-2025-12-15`. This field is not supported when using `gpt-4o-transcribe-diarize`. language: The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format will improve accuracy and latency. prompt: An optional text to guide the model's style or continue a previous audio segment. The [prompt](https://platform.openai.com/docs/guides/speech-to-text#prompting) should match the audio language. response_format: The format of the output, in one of these options: `json`, `text`, `srt`, `verbose_json`, or `vtt`. For `gpt-4o-transcribe` and `gpt-4o-mini-transcribe`, the only supported format is `json`. stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section of the Speech-to-Text guide](https://platform.openai.com/docs/guides/speech-to-text?lang=curl#streaming-transcriptions) for more information. Note: Streaming is not supported for the `whisper-1` model and will be ignored. temperature: The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit. timestamp_granularities: The timestamp granularities to populate for this transcription. `response_format` must be set `verbose_json` to use timestamp granularities. Either or both of these options are supported: `word`, or `segment`. Note: There is no additional latency for segment timestamps, but generating word timestamps incurs additional latency. extra_headers: Send extra headers extra_query: Add additional query parameters to the request """ @overload def create( self, *, file: FileTypes, model: Union[str, AudioModel], chunking_strategy: Optional[transcription_create_params.ChunkingStrategy] | Omit = omit, include: List[TranscriptionInclude] | Omit = omit, response_format: Literal["verbose_json"], language: str | Omit = omit, prompt: str | Omit = omit, temperature: float | Omit = omit, timestamp_granularities: List[Literal["word", "segment"]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TranscriptionVerbose: ... @overload def create( self, *, file: FileTypes, model: Union[str, AudioModel], chunking_strategy: Optional[transcription_create_params.ChunkingStrategy] | Omit = omit, response_format: Literal["text", "srt", "vtt"], include: List[TranscriptionInclude] | Omit = omit, language: str | Omit = omit, prompt: str | Omit = omit, temperature: float | Omit = omit, timestamp_granularities: List[Literal["word", "segment"]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> str: ... @overload def create( self, *, file: FileTypes, model: Union[str, AudioModel], chunking_strategy: Optional[transcription_create_params.ChunkingStrategy] | Omit = omit, response_format: Literal["diarized_json"], known_speaker_names: SequenceNotStr[str] | Omit = omit, known_speaker_references: SequenceNotStr[str] | Omit = omit, language: str | Omit = omit, temperature: float | Omit = omit, timestamp_granularities: List[Literal["word", "segment"]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TranscriptionDiarized: ... @overload def create( self, *, file: FileTypes, model: Union[str, AudioModel], stream: Literal[True], chunking_strategy: Optional[transcription_create_params.ChunkingStrategy] | Omit = omit, include: List[TranscriptionInclude] | Omit = omit, known_speaker_names: SequenceNotStr[str] | Omit = omit, known_speaker_references: SequenceNotStr[str] | Omit = omit, language: str | Omit = omit, prompt: str | Omit = omit, response_format: Union[AudioResponseFormat, Omit] = omit, temperature: float | Omit = omit, timestamp_granularities: List[Literal["word", "segment"]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Stream[TranscriptionStreamEvent]: """ Transcribes audio into the input language. Returns a transcription object in `json`, `diarized_json`, or `verbose_json` format, or a stream of transcript events. Args: file: The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm. model: ID of the model to use. The options are `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `whisper-1` (which is powered by our open source Whisper V2 model), and `gpt-4o-transcribe-diarize`. stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section of the Speech-to-Text guide](https://platform.openai.com/docs/guides/speech-to-text?lang=curl#streaming-transcriptions) for more information. Note: Streaming is not supported for the `whisper-1` model and will be ignored. chunking_strategy: Controls how the audio is cut into chunks. When set to `"auto"`, the server first normalizes loudness and then uses voice activity detection (VAD) to choose boundaries. `server_vad` object can be provided to tweak VAD detection parameters manually. If unset, the audio is transcribed as a single block. Required when using `gpt-4o-transcribe-diarize` for inputs longer than 30 seconds. include: Additional information to include in the transcription response. `logprobs` will return the log probabilities of the tokens in the response to understand the model's confidence in the transcription. `logprobs` only works with response_format set to `json` and only with the models `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, and `gpt-4o-mini-transcribe-2025-12-15`. This field is not supported when using `gpt-4o-transcribe-diarize`. known_speaker_names: Optional list of speaker names that correspond to the audio samples provided in `known_speaker_references[]`. Each entry should be a short identifier (for example `customer` or `agent`). Up to 4 speakers are supported. known_speaker_references: Optional list of audio samples (as [data URLs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs)) that contain known speaker references matching `known_speaker_names[]`. Each sample must be between 2 and 10 seconds, and can use any of the same input audio formats supported by `file`. language: The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format will improve accuracy and latency. prompt: An optional text to guide the model's style or continue a previous audio segment. The [prompt](https://platform.openai.com/docs/guides/speech-to-text#prompting) should match the audio language. This field is not supported when using `gpt-4o-transcribe-diarize`. response_format: The format of the output, in one of these options: `json`, `text`, `srt`, `verbose_json`, `vtt`, or `diarized_json`. For `gpt-4o-transcribe` and `gpt-4o-mini-transcribe`, the only supported format is `json`. For `gpt-4o-transcribe-diarize`, the supported formats are `json`, `text`, and `diarized_json`, with `diarized_json` required to receive speaker annotations. temperature: The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit. timestamp_granularities: The timestamp granularities to populate for this transcription. `response_format` must be set `verbose_json` to use timestamp granularities. Either or both of these options are supported: `word`, or `segment`. Note: There is no additional latency for segment timestamps, but generating word timestamps incurs additional latency. This option is not available for `gpt-4o-transcribe-diarize`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload def create( self, *, file: FileTypes, model: Union[str, AudioModel], stream: bool, chunking_strategy: Optional[transcription_create_params.ChunkingStrategy] | Omit = omit, include: List[TranscriptionInclude] | Omit = omit, known_speaker_names: SequenceNotStr[str] | Omit = omit, known_speaker_references: SequenceNotStr[str] | Omit = omit, language: str | Omit = omit, prompt: str | Omit = omit, response_format: Union[AudioResponseFormat, Omit] = omit, temperature: float | Omit = omit, timestamp_granularities: List[Literal["word", "segment"]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TranscriptionCreateResponse | Stream[TranscriptionStreamEvent]: """ Transcribes audio into the input language. Returns a transcription object in `json`, `diarized_json`, or `verbose_json` format, or a stream of transcript events. Args: file: The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm. model: ID of the model to use. The options are `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `whisper-1` (which is powered by our open source Whisper V2 model), and `gpt-4o-transcribe-diarize`. stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section of the Speech-to-Text guide](https://platform.openai.com/docs/guides/speech-to-text?lang=curl#streaming-transcriptions) for more information. Note: Streaming is not supported for the `whisper-1` model and will be ignored. chunking_strategy: Controls how the audio is cut into chunks. When set to `"auto"`, the server first normalizes loudness and then uses voice activity detection (VAD) to choose boundaries. `server_vad` object can be provided to tweak VAD detection parameters manually. If unset, the audio is transcribed as a single block. Required when using `gpt-4o-transcribe-diarize` for inputs longer than 30 seconds. include: Additional information to include in the transcription response. `logprobs` will return the log probabilities of the tokens in the response to understand the model's confidence in the transcription. `logprobs` only works with response_format set to `json` and only with the models `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, and `gpt-4o-mini-transcribe-2025-12-15`. This field is not supported when using `gpt-4o-transcribe-diarize`. known_speaker_names: Optional list of speaker names that correspond to the audio samples provided in `known_speaker_references[]`. Each entry should be a short identifier (for example `customer` or `agent`). Up to 4 speakers are supported. known_speaker_references: Optional list of audio samples (as [data URLs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs)) that contain known speaker references matching `known_speaker_names[]`. Each sample must be between 2 and 10 seconds, and can use any of the same input audio formats supported by `file`. language: The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format will improve accuracy and latency. prompt: An optional text to guide the model's style or continue a previous audio segment. The [prompt](https://platform.openai.com/docs/guides/speech-to-text#prompting) should match the audio language. This field is not supported when using `gpt-4o-transcribe-diarize`. response_format: The format of the output, in one of these options: `json`, `text`, `srt`, `verbose_json`, `vtt`, or `diarized_json`. For `gpt-4o-transcribe` and `gpt-4o-mini-transcribe`, the only supported format is `json`. For `gpt-4o-transcribe-diarize`, the supported formats are `json`, `text`, and `diarized_json`, with `diarized_json` required to receive speaker annotations. temperature: The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit. timestamp_granularities: The timestamp granularities to populate for this transcription. `response_format` must be set `verbose_json` to use timestamp granularities. Either or both of these options are supported: `word`, or `segment`. Note: There is no additional latency for segment timestamps, but generating word timestamps incurs additional latency. This option is not available for `gpt-4o-transcribe-diarize`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @required_args(["file", "model"], ["file", "model", "stream"]) def create( self, *, file: FileTypes, model: Union[str, AudioModel], chunking_strategy: Optional[transcription_create_params.ChunkingStrategy] | Omit = omit, include: List[TranscriptionInclude] | Omit = omit, known_speaker_names: SequenceNotStr[str] | Omit = omit, known_speaker_references: SequenceNotStr[str] | Omit = omit, language: str | Omit = omit, prompt: str | Omit = omit, response_format: Union[AudioResponseFormat, Omit] = omit, stream: Optional[Literal[False]] | Literal[True] | Omit = omit, temperature: float | Omit = omit, timestamp_granularities: List[Literal["word", "segment"]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> str | Transcription | TranscriptionDiarized | TranscriptionVerbose | Stream[TranscriptionStreamEvent]: body = deepcopy_minimal( { "file": file, "model": model, "chunking_strategy": chunking_strategy, "include": include, "known_speaker_names": known_speaker_names, "known_speaker_references": known_speaker_references, "language": language, "prompt": prompt, "response_format": response_format, "stream": stream, "temperature": temperature, "timestamp_granularities": timestamp_granularities, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return self._post( # type: ignore[return-value] "/audio/transcriptions", body=maybe_transform( body, transcription_create_params.TranscriptionCreateParamsStreaming if stream else transcription_create_params.TranscriptionCreateParamsNonStreaming, ), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=_get_response_format_type(response_format), stream=stream or False, stream_cls=Stream[TranscriptionStreamEvent], ) class AsyncTranscriptions(AsyncAPIResource): """Turn audio into text or text into audio.""" @cached_property def with_raw_response(self) -> AsyncTranscriptionsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncTranscriptionsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncTranscriptionsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncTranscriptionsWithStreamingResponse(self) @overload async def create( self, *, file: FileTypes, model: Union[str, AudioModel], chunking_strategy: Optional[transcription_create_params.ChunkingStrategy] | Omit = omit, include: List[TranscriptionInclude] | Omit = omit, known_speaker_names: SequenceNotStr[str] | Omit = omit, known_speaker_references: SequenceNotStr[str] | Omit = omit, language: str | Omit = omit, prompt: str | Omit = omit, response_format: Union[Literal["json"], Omit] = omit, stream: Optional[Literal[False]] | Omit = omit, temperature: float | Omit = omit, timestamp_granularities: List[Literal["word", "segment"]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TranscriptionCreateResponse: """ Transcribes audio into the input language. Returns a transcription object in `json`, `diarized_json`, or `verbose_json` format, or a stream of transcript events. Args: file: The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm. model: ID of the model to use. The options are `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `whisper-1` (which is powered by our open source Whisper V2 model), and `gpt-4o-transcribe-diarize`. chunking_strategy: Controls how the audio is cut into chunks. When set to `"auto"`, the server first normalizes loudness and then uses voice activity detection (VAD) to choose boundaries. `server_vad` object can be provided to tweak VAD detection parameters manually. If unset, the audio is transcribed as a single block. Required when using `gpt-4o-transcribe-diarize` for inputs longer than 30 seconds. include: Additional information to include in the transcription response. `logprobs` will return the log probabilities of the tokens in the response to understand the model's confidence in the transcription. `logprobs` only works with response_format set to `json` and only with the models `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, and `gpt-4o-mini-transcribe-2025-12-15`. This field is not supported when using `gpt-4o-transcribe-diarize`. known_speaker_names: Optional list of speaker names that correspond to the audio samples provided in `known_speaker_references[]`. Each entry should be a short identifier (for example `customer` or `agent`). Up to 4 speakers are supported. known_speaker_references: Optional list of audio samples (as [data URLs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs)) that contain known speaker references matching `known_speaker_names[]`. Each sample must be between 2 and 10 seconds, and can use any of the same input audio formats supported by `file`. language: The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format will improve accuracy and latency. prompt: An optional text to guide the model's style or continue a previous audio segment. The [prompt](https://platform.openai.com/docs/guides/speech-to-text#prompting) should match the audio language. This field is not supported when using `gpt-4o-transcribe-diarize`. response_format: The format of the output, in one of these options: `json`, `text`, `srt`, `verbose_json`, `vtt`, or `diarized_json`. For `gpt-4o-transcribe` and `gpt-4o-mini-transcribe`, the only supported format is `json`. For `gpt-4o-transcribe-diarize`, the supported formats are `json`, `text`, and `diarized_json`, with `diarized_json` required to receive speaker annotations. stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section of the Speech-to-Text guide](https://platform.openai.com/docs/guides/speech-to-text?lang=curl#streaming-transcriptions) for more information. Note: Streaming is not supported for the `whisper-1` model and will be ignored. temperature: The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit. timestamp_granularities: The timestamp granularities to populate for this transcription. `response_format` must be set `verbose_json` to use timestamp granularities. Either or both of these options are supported: `word`, or `segment`. Note: There is no additional latency for segment timestamps, but generating word timestamps incurs additional latency. This option is not available for `gpt-4o-transcribe-diarize`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request """ @overload async def create( self, *, file: FileTypes, model: Union[str, AudioModel], chunking_strategy: Optional[transcription_create_params.ChunkingStrategy] | Omit = omit, include: List[TranscriptionInclude] | Omit = omit, response_format: Literal["verbose_json"], language: str | Omit = omit, prompt: str | Omit = omit, temperature: float | Omit = omit, timestamp_granularities: List[Literal["word", "segment"]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TranscriptionVerbose: ... @overload async def create( self, *, file: FileTypes, model: Union[str, AudioModel], chunking_strategy: Optional[transcription_create_params.ChunkingStrategy] | Omit = omit, include: List[TranscriptionInclude] | Omit = omit, response_format: Literal["text", "srt", "vtt"], language: str | Omit = omit, prompt: str | Omit = omit, temperature: float | Omit = omit, timestamp_granularities: List[Literal["word", "segment"]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> str: ... @overload async def create( self, *, file: FileTypes, model: Union[str, AudioModel], stream: Literal[True], chunking_strategy: Optional[transcription_create_params.ChunkingStrategy] | Omit = omit, include: List[TranscriptionInclude] | Omit = omit, known_speaker_names: SequenceNotStr[str] | Omit = omit, known_speaker_references: SequenceNotStr[str] | Omit = omit, language: str | Omit = omit, prompt: str | Omit = omit, response_format: Union[AudioResponseFormat, Omit] = omit, temperature: float | Omit = omit, timestamp_granularities: List[Literal["word", "segment"]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncStream[TranscriptionStreamEvent]: """ Transcribes audio into the input language. Returns a transcription object in `json`, `diarized_json`, or `verbose_json` format, or a stream of transcript events. Args: file: The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm. model: ID of the model to use. The options are `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `whisper-1` (which is powered by our open source Whisper V2 model), and `gpt-4o-transcribe-diarize`. stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section of the Speech-to-Text guide](https://platform.openai.com/docs/guides/speech-to-text?lang=curl#streaming-transcriptions) for more information. Note: Streaming is not supported for the `whisper-1` model and will be ignored. chunking_strategy: Controls how the audio is cut into chunks. When set to `"auto"`, the server first normalizes loudness and then uses voice activity detection (VAD) to choose boundaries. `server_vad` object can be provided to tweak VAD detection parameters manually. If unset, the audio is transcribed as a single block. Required when using `gpt-4o-transcribe-diarize` for inputs longer than 30 seconds. include: Additional information to include in the transcription response. `logprobs` will return the log probabilities of the tokens in the response to understand the model's confidence in the transcription. `logprobs` only works with response_format set to `json` and only with the models `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, and `gpt-4o-mini-transcribe-2025-12-15`. This field is not supported when using `gpt-4o-transcribe-diarize`. known_speaker_names: Optional list of speaker names that correspond to the audio samples provided in `known_speaker_references[]`. Each entry should be a short identifier (for example `customer` or `agent`). Up to 4 speakers are supported. known_speaker_references: Optional list of audio samples (as [data URLs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs)) that contain known speaker references matching `known_speaker_names[]`. Each sample must be between 2 and 10 seconds, and can use any of the same input audio formats supported by `file`. language: The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format will improve accuracy and latency. prompt: An optional text to guide the model's style or continue a previous audio segment. The [prompt](https://platform.openai.com/docs/guides/speech-to-text#prompting) should match the audio language. This field is not supported when using `gpt-4o-transcribe-diarize`. response_format: The format of the output, in one of these options: `json`, `text`, `srt`, `verbose_json`, `vtt`, or `diarized_json`. For `gpt-4o-transcribe` and `gpt-4o-mini-transcribe`, the only supported format is `json`. For `gpt-4o-transcribe-diarize`, the supported formats are `json`, `text`, and `diarized_json`, with `diarized_json` required to receive speaker annotations. temperature: The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit. timestamp_granularities: The timestamp granularities to populate for this transcription. `response_format` must be set `verbose_json` to use timestamp granularities. Either or both of these options are supported: `word`, or `segment`. Note: There is no additional latency for segment timestamps, but generating word timestamps incurs additional latency. This option is not available for `gpt-4o-transcribe-diarize`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload async def create( self, *, file: FileTypes, model: Union[str, AudioModel], stream: bool, chunking_strategy: Optional[transcription_create_params.ChunkingStrategy] | Omit = omit, include: List[TranscriptionInclude] | Omit = omit, known_speaker_names: SequenceNotStr[str] | Omit = omit, known_speaker_references: SequenceNotStr[str] | Omit = omit, language: str | Omit = omit, prompt: str | Omit = omit, response_format: Union[AudioResponseFormat, Omit] = omit, temperature: float | Omit = omit, timestamp_granularities: List[Literal["word", "segment"]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TranscriptionCreateResponse | AsyncStream[TranscriptionStreamEvent]: """ Transcribes audio into the input language. Returns a transcription object in `json`, `diarized_json`, or `verbose_json` format, or a stream of transcript events. Args: file: The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm. model: ID of the model to use. The options are `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `whisper-1` (which is powered by our open source Whisper V2 model), and `gpt-4o-transcribe-diarize`. stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section of the Speech-to-Text guide](https://platform.openai.com/docs/guides/speech-to-text?lang=curl#streaming-transcriptions) for more information. Note: Streaming is not supported for the `whisper-1` model and will be ignored. chunking_strategy: Controls how the audio is cut into chunks. When set to `"auto"`, the server first normalizes loudness and then uses voice activity detection (VAD) to choose boundaries. `server_vad` object can be provided to tweak VAD detection parameters manually. If unset, the audio is transcribed as a single block. Required when using `gpt-4o-transcribe-diarize` for inputs longer than 30 seconds. include: Additional information to include in the transcription response. `logprobs` will return the log probabilities of the tokens in the response to understand the model's confidence in the transcription. `logprobs` only works with response_format set to `json` and only with the models `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, and `gpt-4o-mini-transcribe-2025-12-15`. This field is not supported when using `gpt-4o-transcribe-diarize`. known_speaker_names: Optional list of speaker names that correspond to the audio samples provided in `known_speaker_references[]`. Each entry should be a short identifier (for example `customer` or `agent`). Up to 4 speakers are supported. known_speaker_references: Optional list of audio samples (as [data URLs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs)) that contain known speaker references matching `known_speaker_names[]`. Each sample must be between 2 and 10 seconds, and can use any of the same input audio formats supported by `file`. language: The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format will improve accuracy and latency. prompt: An optional text to guide the model's style or continue a previous audio segment. The [prompt](https://platform.openai.com/docs/guides/speech-to-text#prompting) should match the audio language. This field is not supported when using `gpt-4o-transcribe-diarize`. response_format: The format of the output, in one of these options: `json`, `text`, `srt`, `verbose_json`, `vtt`, or `diarized_json`. For `gpt-4o-transcribe` and `gpt-4o-mini-transcribe`, the only supported format is `json`. For `gpt-4o-transcribe-diarize`, the supported formats are `json`, `text`, and `diarized_json`, with `diarized_json` required to receive speaker annotations. temperature: The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit. timestamp_granularities: The timestamp granularities to populate for this transcription. `response_format` must be set `verbose_json` to use timestamp granularities. Either or both of these options are supported: `word`, or `segment`. Note: There is no additional latency for segment timestamps, but generating word timestamps incurs additional latency. This option is not available for `gpt-4o-transcribe-diarize`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @required_args(["file", "model"], ["file", "model", "stream"]) async def create( self, *, file: FileTypes, model: Union[str, AudioModel], chunking_strategy: Optional[transcription_create_params.ChunkingStrategy] | Omit = omit, include: List[TranscriptionInclude] | Omit = omit, known_speaker_names: SequenceNotStr[str] | Omit = omit, known_speaker_references: SequenceNotStr[str] | Omit = omit, language: str | Omit = omit, prompt: str | Omit = omit, response_format: Union[AudioResponseFormat, Omit] = omit, stream: Optional[Literal[False]] | Literal[True] | Omit = omit, temperature: float | Omit = omit, timestamp_granularities: List[Literal["word", "segment"]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Transcription | TranscriptionVerbose | TranscriptionDiarized | str | AsyncStream[TranscriptionStreamEvent]: body = deepcopy_minimal( { "file": file, "model": model, "chunking_strategy": chunking_strategy, "include": include, "known_speaker_names": known_speaker_names, "known_speaker_references": known_speaker_references, "language": language, "prompt": prompt, "response_format": response_format, "stream": stream, "temperature": temperature, "timestamp_granularities": timestamp_granularities, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return await self._post( "/audio/transcriptions", body=await async_maybe_transform( body, transcription_create_params.TranscriptionCreateParamsStreaming if stream else transcription_create_params.TranscriptionCreateParamsNonStreaming, ), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=_get_response_format_type(response_format), stream=stream or False, stream_cls=AsyncStream[TranscriptionStreamEvent], ) class TranscriptionsWithRawResponse: def __init__(self, transcriptions: Transcriptions) -> None: self._transcriptions = transcriptions self.create = _legacy_response.to_raw_response_wrapper( transcriptions.create, ) class AsyncTranscriptionsWithRawResponse: def __init__(self, transcriptions: AsyncTranscriptions) -> None: self._transcriptions = transcriptions self.create = _legacy_response.async_to_raw_response_wrapper( transcriptions.create, ) class TranscriptionsWithStreamingResponse: def __init__(self, transcriptions: Transcriptions) -> None: self._transcriptions = transcriptions self.create = to_streamed_response_wrapper( transcriptions.create, ) class AsyncTranscriptionsWithStreamingResponse: def __init__(self, transcriptions: AsyncTranscriptions) -> None: self._transcriptions = transcriptions self.create = async_to_streamed_response_wrapper( transcriptions.create, ) def _get_response_format_type( response_format: AudioResponseFormat | Omit, ) -> type[Transcription | TranscriptionVerbose | TranscriptionDiarized | str]: if isinstance(response_format, Omit) or response_format is None: # pyright: ignore[reportUnnecessaryComparison] return Transcription if response_format == "json": return Transcription elif response_format == "verbose_json": return TranscriptionVerbose elif response_format == "diarized_json": return TranscriptionDiarized elif response_format == "srt" or response_format == "text" or response_format == "vtt": return str elif TYPE_CHECKING: # type: ignore[unreachable] assert_never(response_format) else: log.warn("Unexpected audio response format: %s", response_format) return Transcription ================================================ FILE: src/openai/resources/audio/translations.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import logging from typing import TYPE_CHECKING, Union, Mapping, cast from typing_extensions import Literal, overload, assert_never import httpx from ... import _legacy_response from ..._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ...types.audio import translation_create_params from ..._base_client import make_request_options from ...types.audio_model import AudioModel from ...types.audio.translation import Translation from ...types.audio_response_format import AudioResponseFormat from ...types.audio.translation_verbose import TranslationVerbose __all__ = ["Translations", "AsyncTranslations"] log: logging.Logger = logging.getLogger("openai.audio.transcriptions") class Translations(SyncAPIResource): """Turn audio into text or text into audio.""" @cached_property def with_raw_response(self) -> TranslationsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return TranslationsWithRawResponse(self) @cached_property def with_streaming_response(self) -> TranslationsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return TranslationsWithStreamingResponse(self) @overload def create( self, *, file: FileTypes, model: Union[str, AudioModel], response_format: Union[Literal["json"], Omit] = omit, prompt: str | Omit = omit, temperature: float | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Translation: ... @overload def create( self, *, file: FileTypes, model: Union[str, AudioModel], response_format: Literal["verbose_json"], prompt: str | Omit = omit, temperature: float | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TranslationVerbose: ... @overload def create( self, *, file: FileTypes, model: Union[str, AudioModel], response_format: Literal["text", "srt", "vtt"], prompt: str | Omit = omit, temperature: float | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> str: ... def create( self, *, file: FileTypes, model: Union[str, AudioModel], prompt: str | Omit = omit, response_format: Union[Literal["json", "text", "srt", "verbose_json", "vtt"], Omit] = omit, temperature: float | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Translation | TranslationVerbose | str: """ Translates audio into English. Args: file: The audio file object (not file name) translate, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm. model: ID of the model to use. Only `whisper-1` (which is powered by our open source Whisper V2 model) is currently available. prompt: An optional text to guide the model's style or continue a previous audio segment. The [prompt](https://platform.openai.com/docs/guides/speech-to-text#prompting) should be in English. response_format: The format of the output, in one of these options: `json`, `text`, `srt`, `verbose_json`, or `vtt`. temperature: The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ body = deepcopy_minimal( { "file": file, "model": model, "prompt": prompt, "response_format": response_format, "temperature": temperature, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return self._post( # type: ignore[return-value] "/audio/translations", body=maybe_transform(body, translation_create_params.TranslationCreateParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=_get_response_format_type(response_format), ) class AsyncTranslations(AsyncAPIResource): """Turn audio into text or text into audio.""" @cached_property def with_raw_response(self) -> AsyncTranslationsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncTranslationsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncTranslationsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncTranslationsWithStreamingResponse(self) @overload async def create( self, *, file: FileTypes, model: Union[str, AudioModel], response_format: Union[Literal["json"], Omit] = omit, prompt: str | Omit = omit, temperature: float | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Translation: ... @overload async def create( self, *, file: FileTypes, model: Union[str, AudioModel], response_format: Literal["verbose_json"], prompt: str | Omit = omit, temperature: float | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TranslationVerbose: ... @overload async def create( self, *, file: FileTypes, model: Union[str, AudioModel], response_format: Literal["text", "srt", "vtt"], prompt: str | Omit = omit, temperature: float | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> str: ... async def create( self, *, file: FileTypes, model: Union[str, AudioModel], prompt: str | Omit = omit, response_format: Union[AudioResponseFormat, Omit] = omit, temperature: float | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Translation | TranslationVerbose | str: """ Translates audio into English. Args: file: The audio file object (not file name) translate, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm. model: ID of the model to use. Only `whisper-1` (which is powered by our open source Whisper V2 model) is currently available. prompt: An optional text to guide the model's style or continue a previous audio segment. The [prompt](https://platform.openai.com/docs/guides/speech-to-text#prompting) should be in English. response_format: The format of the output, in one of these options: `json`, `text`, `srt`, `verbose_json`, or `vtt`. temperature: The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ body = deepcopy_minimal( { "file": file, "model": model, "prompt": prompt, "response_format": response_format, "temperature": temperature, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return await self._post( "/audio/translations", body=await async_maybe_transform(body, translation_create_params.TranslationCreateParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=_get_response_format_type(response_format), ) class TranslationsWithRawResponse: def __init__(self, translations: Translations) -> None: self._translations = translations self.create = _legacy_response.to_raw_response_wrapper( translations.create, ) class AsyncTranslationsWithRawResponse: def __init__(self, translations: AsyncTranslations) -> None: self._translations = translations self.create = _legacy_response.async_to_raw_response_wrapper( translations.create, ) class TranslationsWithStreamingResponse: def __init__(self, translations: Translations) -> None: self._translations = translations self.create = to_streamed_response_wrapper( translations.create, ) class AsyncTranslationsWithStreamingResponse: def __init__(self, translations: AsyncTranslations) -> None: self._translations = translations self.create = async_to_streamed_response_wrapper( translations.create, ) def _get_response_format_type( response_format: AudioResponseFormat | Omit, ) -> type[Translation | TranslationVerbose | str]: if isinstance(response_format, Omit) or response_format is None: # pyright: ignore[reportUnnecessaryComparison] return Translation if response_format == "json": return Translation elif response_format == "verbose_json": return TranslationVerbose elif response_format == "srt" or response_format == "text" or response_format == "vtt": return str elif TYPE_CHECKING and response_format != "diarized_json": # type: ignore[unreachable] assert_never(response_format) else: log.warning("Unexpected audio response format: %s", response_format) return Translation ================================================ FILE: src/openai/resources/batches.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Literal import httpx from .. import _legacy_response from ..types import batch_list_params, batch_create_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ..pagination import SyncCursorPage, AsyncCursorPage from ..types.batch import Batch from .._base_client import AsyncPaginator, make_request_options from ..types.shared_params.metadata import Metadata __all__ = ["Batches", "AsyncBatches"] class Batches(SyncAPIResource): """Create large batches of API requests to run asynchronously.""" @cached_property def with_raw_response(self) -> BatchesWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return BatchesWithRawResponse(self) @cached_property def with_streaming_response(self) -> BatchesWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return BatchesWithStreamingResponse(self) def create( self, *, completion_window: Literal["24h"], endpoint: Literal[ "/v1/responses", "/v1/chat/completions", "/v1/embeddings", "/v1/completions", "/v1/moderations", "/v1/images/generations", "/v1/images/edits", "/v1/videos", ], input_file_id: str, metadata: Optional[Metadata] | Omit = omit, output_expires_after: batch_create_params.OutputExpiresAfter | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Batch: """ Creates and executes a batch from an uploaded file of requests Args: completion_window: The time frame within which the batch should be processed. Currently only `24h` is supported. endpoint: The endpoint to be used for all requests in the batch. Currently `/v1/responses`, `/v1/chat/completions`, `/v1/embeddings`, `/v1/completions`, `/v1/moderations`, `/v1/images/generations`, `/v1/images/edits`, and `/v1/videos` are supported. Note that `/v1/embeddings` batches are also restricted to a maximum of 50,000 embedding inputs across all requests in the batch. input_file_id: The ID of an uploaded file that contains requests for the new batch. See [upload file](https://platform.openai.com/docs/api-reference/files/create) for how to upload a file. Your input file must be formatted as a [JSONL file](https://platform.openai.com/docs/api-reference/batch/request-input), and must be uploaded with the purpose `batch`. The file can contain up to 50,000 requests, and can be up to 200 MB in size. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. output_expires_after: The expiration policy for the output and/or error file that are generated for a batch. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._post( "/batches", body=maybe_transform( { "completion_window": completion_window, "endpoint": endpoint, "input_file_id": input_file_id, "metadata": metadata, "output_expires_after": output_expires_after, }, batch_create_params.BatchCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Batch, ) def retrieve( self, batch_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Batch: """ Retrieves a batch. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not batch_id: raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}") return self._get( f"/batches/{batch_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Batch, ) def list( self, *, after: str | Omit = omit, limit: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[Batch]: """List your organization's batches. Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._get_api_list( "/batches", page=SyncCursorPage[Batch], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, }, batch_list_params.BatchListParams, ), ), model=Batch, ) def cancel( self, batch_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Batch: """Cancels an in-progress batch. The batch will be in status `cancelling` for up to 10 minutes, before changing to `cancelled`, where it will have partial results (if any) available in the output file. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not batch_id: raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}") return self._post( f"/batches/{batch_id}/cancel", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Batch, ) class AsyncBatches(AsyncAPIResource): """Create large batches of API requests to run asynchronously.""" @cached_property def with_raw_response(self) -> AsyncBatchesWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncBatchesWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncBatchesWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncBatchesWithStreamingResponse(self) async def create( self, *, completion_window: Literal["24h"], endpoint: Literal[ "/v1/responses", "/v1/chat/completions", "/v1/embeddings", "/v1/completions", "/v1/moderations", "/v1/images/generations", "/v1/images/edits", "/v1/videos", ], input_file_id: str, metadata: Optional[Metadata] | Omit = omit, output_expires_after: batch_create_params.OutputExpiresAfter | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Batch: """ Creates and executes a batch from an uploaded file of requests Args: completion_window: The time frame within which the batch should be processed. Currently only `24h` is supported. endpoint: The endpoint to be used for all requests in the batch. Currently `/v1/responses`, `/v1/chat/completions`, `/v1/embeddings`, `/v1/completions`, `/v1/moderations`, `/v1/images/generations`, `/v1/images/edits`, and `/v1/videos` are supported. Note that `/v1/embeddings` batches are also restricted to a maximum of 50,000 embedding inputs across all requests in the batch. input_file_id: The ID of an uploaded file that contains requests for the new batch. See [upload file](https://platform.openai.com/docs/api-reference/files/create) for how to upload a file. Your input file must be formatted as a [JSONL file](https://platform.openai.com/docs/api-reference/batch/request-input), and must be uploaded with the purpose `batch`. The file can contain up to 50,000 requests, and can be up to 200 MB in size. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. output_expires_after: The expiration policy for the output and/or error file that are generated for a batch. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return await self._post( "/batches", body=await async_maybe_transform( { "completion_window": completion_window, "endpoint": endpoint, "input_file_id": input_file_id, "metadata": metadata, "output_expires_after": output_expires_after, }, batch_create_params.BatchCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Batch, ) async def retrieve( self, batch_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Batch: """ Retrieves a batch. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not batch_id: raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}") return await self._get( f"/batches/{batch_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Batch, ) def list( self, *, after: str | Omit = omit, limit: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[Batch, AsyncCursorPage[Batch]]: """List your organization's batches. Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._get_api_list( "/batches", page=AsyncCursorPage[Batch], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, }, batch_list_params.BatchListParams, ), ), model=Batch, ) async def cancel( self, batch_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Batch: """Cancels an in-progress batch. The batch will be in status `cancelling` for up to 10 minutes, before changing to `cancelled`, where it will have partial results (if any) available in the output file. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not batch_id: raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}") return await self._post( f"/batches/{batch_id}/cancel", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Batch, ) class BatchesWithRawResponse: def __init__(self, batches: Batches) -> None: self._batches = batches self.create = _legacy_response.to_raw_response_wrapper( batches.create, ) self.retrieve = _legacy_response.to_raw_response_wrapper( batches.retrieve, ) self.list = _legacy_response.to_raw_response_wrapper( batches.list, ) self.cancel = _legacy_response.to_raw_response_wrapper( batches.cancel, ) class AsyncBatchesWithRawResponse: def __init__(self, batches: AsyncBatches) -> None: self._batches = batches self.create = _legacy_response.async_to_raw_response_wrapper( batches.create, ) self.retrieve = _legacy_response.async_to_raw_response_wrapper( batches.retrieve, ) self.list = _legacy_response.async_to_raw_response_wrapper( batches.list, ) self.cancel = _legacy_response.async_to_raw_response_wrapper( batches.cancel, ) class BatchesWithStreamingResponse: def __init__(self, batches: Batches) -> None: self._batches = batches self.create = to_streamed_response_wrapper( batches.create, ) self.retrieve = to_streamed_response_wrapper( batches.retrieve, ) self.list = to_streamed_response_wrapper( batches.list, ) self.cancel = to_streamed_response_wrapper( batches.cancel, ) class AsyncBatchesWithStreamingResponse: def __init__(self, batches: AsyncBatches) -> None: self._batches = batches self.create = async_to_streamed_response_wrapper( batches.create, ) self.retrieve = async_to_streamed_response_wrapper( batches.retrieve, ) self.list = async_to_streamed_response_wrapper( batches.list, ) self.cancel = async_to_streamed_response_wrapper( batches.cancel, ) ================================================ FILE: src/openai/resources/beta/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .beta import ( Beta, AsyncBeta, BetaWithRawResponse, AsyncBetaWithRawResponse, BetaWithStreamingResponse, AsyncBetaWithStreamingResponse, ) from .chatkit import ( ChatKit, AsyncChatKit, ChatKitWithRawResponse, AsyncChatKitWithRawResponse, ChatKitWithStreamingResponse, AsyncChatKitWithStreamingResponse, ) from .threads import ( Threads, AsyncThreads, ThreadsWithRawResponse, AsyncThreadsWithRawResponse, ThreadsWithStreamingResponse, AsyncThreadsWithStreamingResponse, ) from .assistants import ( Assistants, AsyncAssistants, AssistantsWithRawResponse, AsyncAssistantsWithRawResponse, AssistantsWithStreamingResponse, AsyncAssistantsWithStreamingResponse, ) __all__ = [ "ChatKit", "AsyncChatKit", "ChatKitWithRawResponse", "AsyncChatKitWithRawResponse", "ChatKitWithStreamingResponse", "AsyncChatKitWithStreamingResponse", "Assistants", "AsyncAssistants", "AssistantsWithRawResponse", "AsyncAssistantsWithRawResponse", "AssistantsWithStreamingResponse", "AsyncAssistantsWithStreamingResponse", "Threads", "AsyncThreads", "ThreadsWithRawResponse", "AsyncThreadsWithRawResponse", "ThreadsWithStreamingResponse", "AsyncThreadsWithStreamingResponse", "Beta", "AsyncBeta", "BetaWithRawResponse", "AsyncBetaWithRawResponse", "BetaWithStreamingResponse", "AsyncBetaWithStreamingResponse", ] ================================================ FILE: src/openai/resources/beta/assistants.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import typing_extensions from typing import Union, Iterable, Optional from typing_extensions import Literal import httpx from ... import _legacy_response from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ...pagination import SyncCursorPage, AsyncCursorPage from ...types.beta import ( assistant_list_params, assistant_create_params, assistant_update_params, ) from ..._base_client import AsyncPaginator, make_request_options from ...types.beta.assistant import Assistant from ...types.shared.chat_model import ChatModel from ...types.beta.assistant_deleted import AssistantDeleted from ...types.shared_params.metadata import Metadata from ...types.shared.reasoning_effort import ReasoningEffort from ...types.beta.assistant_tool_param import AssistantToolParam from ...types.beta.assistant_response_format_option_param import AssistantResponseFormatOptionParam __all__ = ["Assistants", "AsyncAssistants"] class Assistants(SyncAPIResource): """Build Assistants that can call models and use tools.""" @cached_property def with_raw_response(self) -> AssistantsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AssistantsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AssistantsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AssistantsWithStreamingResponse(self) @typing_extensions.deprecated("deprecated") def create( self, *, model: Union[str, ChatModel], description: Optional[str] | Omit = omit, instructions: Optional[str] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, name: Optional[str] | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_resources: Optional[assistant_create_params.ToolResources] | Omit = omit, tools: Iterable[AssistantToolParam] | Omit = omit, top_p: Optional[float] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Assistant: """ Create an assistant with a model and instructions. Args: model: ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models) for descriptions of them. description: The description of the assistant. The maximum length is 512 characters. instructions: The system instructions that the assistant uses. The maximum length is 256,000 characters. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. name: The name of the assistant. The maximum length is 256 characters. reasoning_effort: Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. response_format: Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. tool_resources: A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. tools: A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `file_search`, or `function`. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._post( "/assistants", body=maybe_transform( { "model": model, "description": description, "instructions": instructions, "metadata": metadata, "name": name, "reasoning_effort": reasoning_effort, "response_format": response_format, "temperature": temperature, "tool_resources": tool_resources, "tools": tools, "top_p": top_p, }, assistant_create_params.AssistantCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Assistant, ) @typing_extensions.deprecated("deprecated") def retrieve( self, assistant_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Assistant: """ Retrieves an assistant. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not assistant_id: raise ValueError(f"Expected a non-empty value for `assistant_id` but received {assistant_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get( f"/assistants/{assistant_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Assistant, ) @typing_extensions.deprecated("deprecated") def update( self, assistant_id: str, *, description: Optional[str] | Omit = omit, instructions: Optional[str] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[ str, Literal[ "gpt-5", "gpt-5-mini", "gpt-5-nano", "gpt-5-2025-08-07", "gpt-5-mini-2025-08-07", "gpt-5-nano-2025-08-07", "gpt-4.1", "gpt-4.1-mini", "gpt-4.1-nano", "gpt-4.1-2025-04-14", "gpt-4.1-mini-2025-04-14", "gpt-4.1-nano-2025-04-14", "o3-mini", "o3-mini-2025-01-31", "o1", "o1-2024-12-17", "gpt-4o", "gpt-4o-2024-11-20", "gpt-4o-2024-08-06", "gpt-4o-2024-05-13", "gpt-4o-mini", "gpt-4o-mini-2024-07-18", "gpt-4.5-preview", "gpt-4.5-preview-2025-02-27", "gpt-4-turbo", "gpt-4-turbo-2024-04-09", "gpt-4-0125-preview", "gpt-4-turbo-preview", "gpt-4-1106-preview", "gpt-4-vision-preview", "gpt-4", "gpt-4-0314", "gpt-4-0613", "gpt-4-32k", "gpt-4-32k-0314", "gpt-4-32k-0613", "gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-3.5-turbo-0613", "gpt-3.5-turbo-1106", "gpt-3.5-turbo-0125", "gpt-3.5-turbo-16k-0613", ], ] | Omit = omit, name: Optional[str] | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_resources: Optional[assistant_update_params.ToolResources] | Omit = omit, tools: Iterable[AssistantToolParam] | Omit = omit, top_p: Optional[float] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Assistant: """Modifies an assistant. Args: description: The description of the assistant. The maximum length is 512 characters. instructions: The system instructions that the assistant uses. The maximum length is 256,000 characters. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models) for descriptions of them. name: The name of the assistant. The maximum length is 256 characters. reasoning_effort: Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. response_format: Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. tool_resources: A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. tools: A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `file_search`, or `function`. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not assistant_id: raise ValueError(f"Expected a non-empty value for `assistant_id` but received {assistant_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._post( f"/assistants/{assistant_id}", body=maybe_transform( { "description": description, "instructions": instructions, "metadata": metadata, "model": model, "name": name, "reasoning_effort": reasoning_effort, "response_format": response_format, "temperature": temperature, "tool_resources": tool_resources, "tools": tools, "top_p": top_p, }, assistant_update_params.AssistantUpdateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Assistant, ) @typing_extensions.deprecated("deprecated") def list( self, *, after: str | Omit = omit, before: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[Assistant]: """Returns a list of assistants. Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. before: A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get_api_list( "/assistants", page=SyncCursorPage[Assistant], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "limit": limit, "order": order, }, assistant_list_params.AssistantListParams, ), ), model=Assistant, ) @typing_extensions.deprecated("deprecated") def delete( self, assistant_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AssistantDeleted: """ Delete an assistant. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not assistant_id: raise ValueError(f"Expected a non-empty value for `assistant_id` but received {assistant_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._delete( f"/assistants/{assistant_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=AssistantDeleted, ) class AsyncAssistants(AsyncAPIResource): """Build Assistants that can call models and use tools.""" @cached_property def with_raw_response(self) -> AsyncAssistantsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncAssistantsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncAssistantsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncAssistantsWithStreamingResponse(self) @typing_extensions.deprecated("deprecated") async def create( self, *, model: Union[str, ChatModel], description: Optional[str] | Omit = omit, instructions: Optional[str] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, name: Optional[str] | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_resources: Optional[assistant_create_params.ToolResources] | Omit = omit, tools: Iterable[AssistantToolParam] | Omit = omit, top_p: Optional[float] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Assistant: """ Create an assistant with a model and instructions. Args: model: ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models) for descriptions of them. description: The description of the assistant. The maximum length is 512 characters. instructions: The system instructions that the assistant uses. The maximum length is 256,000 characters. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. name: The name of the assistant. The maximum length is 256 characters. reasoning_effort: Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. response_format: Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. tool_resources: A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. tools: A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `file_search`, or `function`. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._post( "/assistants", body=await async_maybe_transform( { "model": model, "description": description, "instructions": instructions, "metadata": metadata, "name": name, "reasoning_effort": reasoning_effort, "response_format": response_format, "temperature": temperature, "tool_resources": tool_resources, "tools": tools, "top_p": top_p, }, assistant_create_params.AssistantCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Assistant, ) @typing_extensions.deprecated("deprecated") async def retrieve( self, assistant_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Assistant: """ Retrieves an assistant. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not assistant_id: raise ValueError(f"Expected a non-empty value for `assistant_id` but received {assistant_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._get( f"/assistants/{assistant_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Assistant, ) @typing_extensions.deprecated("deprecated") async def update( self, assistant_id: str, *, description: Optional[str] | Omit = omit, instructions: Optional[str] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[ str, Literal[ "gpt-5", "gpt-5-mini", "gpt-5-nano", "gpt-5-2025-08-07", "gpt-5-mini-2025-08-07", "gpt-5-nano-2025-08-07", "gpt-4.1", "gpt-4.1-mini", "gpt-4.1-nano", "gpt-4.1-2025-04-14", "gpt-4.1-mini-2025-04-14", "gpt-4.1-nano-2025-04-14", "o3-mini", "o3-mini-2025-01-31", "o1", "o1-2024-12-17", "gpt-4o", "gpt-4o-2024-11-20", "gpt-4o-2024-08-06", "gpt-4o-2024-05-13", "gpt-4o-mini", "gpt-4o-mini-2024-07-18", "gpt-4.5-preview", "gpt-4.5-preview-2025-02-27", "gpt-4-turbo", "gpt-4-turbo-2024-04-09", "gpt-4-0125-preview", "gpt-4-turbo-preview", "gpt-4-1106-preview", "gpt-4-vision-preview", "gpt-4", "gpt-4-0314", "gpt-4-0613", "gpt-4-32k", "gpt-4-32k-0314", "gpt-4-32k-0613", "gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-3.5-turbo-0613", "gpt-3.5-turbo-1106", "gpt-3.5-turbo-0125", "gpt-3.5-turbo-16k-0613", ], ] | Omit = omit, name: Optional[str] | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_resources: Optional[assistant_update_params.ToolResources] | Omit = omit, tools: Iterable[AssistantToolParam] | Omit = omit, top_p: Optional[float] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Assistant: """Modifies an assistant. Args: description: The description of the assistant. The maximum length is 512 characters. instructions: The system instructions that the assistant uses. The maximum length is 256,000 characters. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models) for descriptions of them. name: The name of the assistant. The maximum length is 256 characters. reasoning_effort: Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. response_format: Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. tool_resources: A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. tools: A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `file_search`, or `function`. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not assistant_id: raise ValueError(f"Expected a non-empty value for `assistant_id` but received {assistant_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._post( f"/assistants/{assistant_id}", body=await async_maybe_transform( { "description": description, "instructions": instructions, "metadata": metadata, "model": model, "name": name, "reasoning_effort": reasoning_effort, "response_format": response_format, "temperature": temperature, "tool_resources": tool_resources, "tools": tools, "top_p": top_p, }, assistant_update_params.AssistantUpdateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Assistant, ) @typing_extensions.deprecated("deprecated") def list( self, *, after: str | Omit = omit, before: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[Assistant, AsyncCursorPage[Assistant]]: """Returns a list of assistants. Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. before: A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get_api_list( "/assistants", page=AsyncCursorPage[Assistant], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "limit": limit, "order": order, }, assistant_list_params.AssistantListParams, ), ), model=Assistant, ) @typing_extensions.deprecated("deprecated") async def delete( self, assistant_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AssistantDeleted: """ Delete an assistant. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not assistant_id: raise ValueError(f"Expected a non-empty value for `assistant_id` but received {assistant_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._delete( f"/assistants/{assistant_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=AssistantDeleted, ) class AssistantsWithRawResponse: def __init__(self, assistants: Assistants) -> None: self._assistants = assistants self.create = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( assistants.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( assistants.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( assistants.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( assistants.list, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( assistants.delete, # pyright: ignore[reportDeprecated], ) ) class AsyncAssistantsWithRawResponse: def __init__(self, assistants: AsyncAssistants) -> None: self._assistants = assistants self.create = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( assistants.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( assistants.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( assistants.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( assistants.list, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( assistants.delete, # pyright: ignore[reportDeprecated], ) ) class AssistantsWithStreamingResponse: def __init__(self, assistants: Assistants) -> None: self._assistants = assistants self.create = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( assistants.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( assistants.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( assistants.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( assistants.list, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( assistants.delete, # pyright: ignore[reportDeprecated], ) ) class AsyncAssistantsWithStreamingResponse: def __init__(self, assistants: AsyncAssistants) -> None: self._assistants = assistants self.create = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( assistants.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( assistants.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( assistants.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( assistants.list, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( assistants.delete, # pyright: ignore[reportDeprecated], ) ) ================================================ FILE: src/openai/resources/beta/beta.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from ..._compat import cached_property from .assistants import ( Assistants, AsyncAssistants, AssistantsWithRawResponse, AsyncAssistantsWithRawResponse, AssistantsWithStreamingResponse, AsyncAssistantsWithStreamingResponse, ) from ..._resource import SyncAPIResource, AsyncAPIResource from .chatkit.chatkit import ( ChatKit, AsyncChatKit, ChatKitWithRawResponse, AsyncChatKitWithRawResponse, ChatKitWithStreamingResponse, AsyncChatKitWithStreamingResponse, ) from .threads.threads import ( Threads, AsyncThreads, ThreadsWithRawResponse, AsyncThreadsWithRawResponse, ThreadsWithStreamingResponse, AsyncThreadsWithStreamingResponse, ) from ...resources.chat import Chat, AsyncChat from .realtime.realtime import ( Realtime, AsyncRealtime, ) __all__ = ["Beta", "AsyncBeta"] class Beta(SyncAPIResource): @cached_property def chat(self) -> Chat: return Chat(self._client) @cached_property def realtime(self) -> Realtime: return Realtime(self._client) @cached_property def chatkit(self) -> ChatKit: return ChatKit(self._client) @cached_property def assistants(self) -> Assistants: """Build Assistants that can call models and use tools.""" return Assistants(self._client) @cached_property def threads(self) -> Threads: """Build Assistants that can call models and use tools.""" return Threads(self._client) @cached_property def with_raw_response(self) -> BetaWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return BetaWithRawResponse(self) @cached_property def with_streaming_response(self) -> BetaWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return BetaWithStreamingResponse(self) class AsyncBeta(AsyncAPIResource): @cached_property def chat(self) -> AsyncChat: return AsyncChat(self._client) @cached_property def realtime(self) -> AsyncRealtime: return AsyncRealtime(self._client) @cached_property def chatkit(self) -> AsyncChatKit: return AsyncChatKit(self._client) @cached_property def assistants(self) -> AsyncAssistants: """Build Assistants that can call models and use tools.""" return AsyncAssistants(self._client) @cached_property def threads(self) -> AsyncThreads: """Build Assistants that can call models and use tools.""" return AsyncThreads(self._client) @cached_property def with_raw_response(self) -> AsyncBetaWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncBetaWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncBetaWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncBetaWithStreamingResponse(self) class BetaWithRawResponse: def __init__(self, beta: Beta) -> None: self._beta = beta @cached_property def chatkit(self) -> ChatKitWithRawResponse: return ChatKitWithRawResponse(self._beta.chatkit) @cached_property def assistants(self) -> AssistantsWithRawResponse: """Build Assistants that can call models and use tools.""" return AssistantsWithRawResponse(self._beta.assistants) @cached_property def threads(self) -> ThreadsWithRawResponse: """Build Assistants that can call models and use tools.""" return ThreadsWithRawResponse(self._beta.threads) class AsyncBetaWithRawResponse: def __init__(self, beta: AsyncBeta) -> None: self._beta = beta @cached_property def chatkit(self) -> AsyncChatKitWithRawResponse: return AsyncChatKitWithRawResponse(self._beta.chatkit) @cached_property def assistants(self) -> AsyncAssistantsWithRawResponse: """Build Assistants that can call models and use tools.""" return AsyncAssistantsWithRawResponse(self._beta.assistants) @cached_property def threads(self) -> AsyncThreadsWithRawResponse: """Build Assistants that can call models and use tools.""" return AsyncThreadsWithRawResponse(self._beta.threads) class BetaWithStreamingResponse: def __init__(self, beta: Beta) -> None: self._beta = beta @cached_property def chatkit(self) -> ChatKitWithStreamingResponse: return ChatKitWithStreamingResponse(self._beta.chatkit) @cached_property def assistants(self) -> AssistantsWithStreamingResponse: """Build Assistants that can call models and use tools.""" return AssistantsWithStreamingResponse(self._beta.assistants) @cached_property def threads(self) -> ThreadsWithStreamingResponse: """Build Assistants that can call models and use tools.""" return ThreadsWithStreamingResponse(self._beta.threads) class AsyncBetaWithStreamingResponse: def __init__(self, beta: AsyncBeta) -> None: self._beta = beta @cached_property def chatkit(self) -> AsyncChatKitWithStreamingResponse: return AsyncChatKitWithStreamingResponse(self._beta.chatkit) @cached_property def assistants(self) -> AsyncAssistantsWithStreamingResponse: """Build Assistants that can call models and use tools.""" return AsyncAssistantsWithStreamingResponse(self._beta.assistants) @cached_property def threads(self) -> AsyncThreadsWithStreamingResponse: """Build Assistants that can call models and use tools.""" return AsyncThreadsWithStreamingResponse(self._beta.threads) ================================================ FILE: src/openai/resources/beta/chatkit/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .chatkit import ( ChatKit, AsyncChatKit, ChatKitWithRawResponse, AsyncChatKitWithRawResponse, ChatKitWithStreamingResponse, AsyncChatKitWithStreamingResponse, ) from .threads import ( Threads, AsyncThreads, ThreadsWithRawResponse, AsyncThreadsWithRawResponse, ThreadsWithStreamingResponse, AsyncThreadsWithStreamingResponse, ) from .sessions import ( Sessions, AsyncSessions, SessionsWithRawResponse, AsyncSessionsWithRawResponse, SessionsWithStreamingResponse, AsyncSessionsWithStreamingResponse, ) __all__ = [ "Sessions", "AsyncSessions", "SessionsWithRawResponse", "AsyncSessionsWithRawResponse", "SessionsWithStreamingResponse", "AsyncSessionsWithStreamingResponse", "Threads", "AsyncThreads", "ThreadsWithRawResponse", "AsyncThreadsWithRawResponse", "ThreadsWithStreamingResponse", "AsyncThreadsWithStreamingResponse", "ChatKit", "AsyncChatKit", "ChatKitWithRawResponse", "AsyncChatKitWithRawResponse", "ChatKitWithStreamingResponse", "AsyncChatKitWithStreamingResponse", ] ================================================ FILE: src/openai/resources/beta/chatkit/chatkit.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .threads import ( Threads, AsyncThreads, ThreadsWithRawResponse, AsyncThreadsWithRawResponse, ThreadsWithStreamingResponse, AsyncThreadsWithStreamingResponse, ) from .sessions import ( Sessions, AsyncSessions, SessionsWithRawResponse, AsyncSessionsWithRawResponse, SessionsWithStreamingResponse, AsyncSessionsWithStreamingResponse, ) from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource __all__ = ["ChatKit", "AsyncChatKit"] class ChatKit(SyncAPIResource): @cached_property def sessions(self) -> Sessions: return Sessions(self._client) @cached_property def threads(self) -> Threads: return Threads(self._client) @cached_property def with_raw_response(self) -> ChatKitWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return ChatKitWithRawResponse(self) @cached_property def with_streaming_response(self) -> ChatKitWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return ChatKitWithStreamingResponse(self) class AsyncChatKit(AsyncAPIResource): @cached_property def sessions(self) -> AsyncSessions: return AsyncSessions(self._client) @cached_property def threads(self) -> AsyncThreads: return AsyncThreads(self._client) @cached_property def with_raw_response(self) -> AsyncChatKitWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncChatKitWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncChatKitWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncChatKitWithStreamingResponse(self) class ChatKitWithRawResponse: def __init__(self, chatkit: ChatKit) -> None: self._chatkit = chatkit @cached_property def sessions(self) -> SessionsWithRawResponse: return SessionsWithRawResponse(self._chatkit.sessions) @cached_property def threads(self) -> ThreadsWithRawResponse: return ThreadsWithRawResponse(self._chatkit.threads) class AsyncChatKitWithRawResponse: def __init__(self, chatkit: AsyncChatKit) -> None: self._chatkit = chatkit @cached_property def sessions(self) -> AsyncSessionsWithRawResponse: return AsyncSessionsWithRawResponse(self._chatkit.sessions) @cached_property def threads(self) -> AsyncThreadsWithRawResponse: return AsyncThreadsWithRawResponse(self._chatkit.threads) class ChatKitWithStreamingResponse: def __init__(self, chatkit: ChatKit) -> None: self._chatkit = chatkit @cached_property def sessions(self) -> SessionsWithStreamingResponse: return SessionsWithStreamingResponse(self._chatkit.sessions) @cached_property def threads(self) -> ThreadsWithStreamingResponse: return ThreadsWithStreamingResponse(self._chatkit.threads) class AsyncChatKitWithStreamingResponse: def __init__(self, chatkit: AsyncChatKit) -> None: self._chatkit = chatkit @cached_property def sessions(self) -> AsyncSessionsWithStreamingResponse: return AsyncSessionsWithStreamingResponse(self._chatkit.sessions) @cached_property def threads(self) -> AsyncThreadsWithStreamingResponse: return AsyncThreadsWithStreamingResponse(self._chatkit.threads) ================================================ FILE: src/openai/resources/beta/chatkit/sessions.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import httpx from .... import _legacy_response from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ...._utils import maybe_transform, async_maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ...._base_client import make_request_options from ....types.beta.chatkit import ( ChatSessionWorkflowParam, ChatSessionRateLimitsParam, ChatSessionExpiresAfterParam, ChatSessionChatKitConfigurationParam, session_create_params, ) from ....types.beta.chatkit.chat_session import ChatSession from ....types.beta.chatkit.chat_session_workflow_param import ChatSessionWorkflowParam from ....types.beta.chatkit.chat_session_rate_limits_param import ChatSessionRateLimitsParam from ....types.beta.chatkit.chat_session_expires_after_param import ChatSessionExpiresAfterParam from ....types.beta.chatkit.chat_session_chatkit_configuration_param import ChatSessionChatKitConfigurationParam __all__ = ["Sessions", "AsyncSessions"] class Sessions(SyncAPIResource): @cached_property def with_raw_response(self) -> SessionsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return SessionsWithRawResponse(self) @cached_property def with_streaming_response(self) -> SessionsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return SessionsWithStreamingResponse(self) def create( self, *, user: str, workflow: ChatSessionWorkflowParam, chatkit_configuration: ChatSessionChatKitConfigurationParam | Omit = omit, expires_after: ChatSessionExpiresAfterParam | Omit = omit, rate_limits: ChatSessionRateLimitsParam | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatSession: """ Create a ChatKit session. Args: user: A free-form string that identifies your end user; ensures this Session can access other objects that have the same `user` scope. workflow: Workflow that powers the session. chatkit_configuration: Optional overrides for ChatKit runtime configuration features expires_after: Optional override for session expiration timing in seconds from creation. Defaults to 10 minutes. rate_limits: Optional override for per-minute request limits. When omitted, defaults to 10. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"OpenAI-Beta": "chatkit_beta=v1", **(extra_headers or {})} return self._post( "/chatkit/sessions", body=maybe_transform( { "user": user, "workflow": workflow, "chatkit_configuration": chatkit_configuration, "expires_after": expires_after, "rate_limits": rate_limits, }, session_create_params.SessionCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ChatSession, ) def cancel( self, session_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatSession: """ Cancel an active ChatKit session and return its most recent metadata. Cancelling prevents new requests from using the issued client secret. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not session_id: raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") extra_headers = {"OpenAI-Beta": "chatkit_beta=v1", **(extra_headers or {})} return self._post( f"/chatkit/sessions/{session_id}/cancel", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ChatSession, ) class AsyncSessions(AsyncAPIResource): @cached_property def with_raw_response(self) -> AsyncSessionsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncSessionsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncSessionsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncSessionsWithStreamingResponse(self) async def create( self, *, user: str, workflow: ChatSessionWorkflowParam, chatkit_configuration: ChatSessionChatKitConfigurationParam | Omit = omit, expires_after: ChatSessionExpiresAfterParam | Omit = omit, rate_limits: ChatSessionRateLimitsParam | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatSession: """ Create a ChatKit session. Args: user: A free-form string that identifies your end user; ensures this Session can access other objects that have the same `user` scope. workflow: Workflow that powers the session. chatkit_configuration: Optional overrides for ChatKit runtime configuration features expires_after: Optional override for session expiration timing in seconds from creation. Defaults to 10 minutes. rate_limits: Optional override for per-minute request limits. When omitted, defaults to 10. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"OpenAI-Beta": "chatkit_beta=v1", **(extra_headers or {})} return await self._post( "/chatkit/sessions", body=await async_maybe_transform( { "user": user, "workflow": workflow, "chatkit_configuration": chatkit_configuration, "expires_after": expires_after, "rate_limits": rate_limits, }, session_create_params.SessionCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ChatSession, ) async def cancel( self, session_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatSession: """ Cancel an active ChatKit session and return its most recent metadata. Cancelling prevents new requests from using the issued client secret. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not session_id: raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") extra_headers = {"OpenAI-Beta": "chatkit_beta=v1", **(extra_headers or {})} return await self._post( f"/chatkit/sessions/{session_id}/cancel", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ChatSession, ) class SessionsWithRawResponse: def __init__(self, sessions: Sessions) -> None: self._sessions = sessions self.create = _legacy_response.to_raw_response_wrapper( sessions.create, ) self.cancel = _legacy_response.to_raw_response_wrapper( sessions.cancel, ) class AsyncSessionsWithRawResponse: def __init__(self, sessions: AsyncSessions) -> None: self._sessions = sessions self.create = _legacy_response.async_to_raw_response_wrapper( sessions.create, ) self.cancel = _legacy_response.async_to_raw_response_wrapper( sessions.cancel, ) class SessionsWithStreamingResponse: def __init__(self, sessions: Sessions) -> None: self._sessions = sessions self.create = to_streamed_response_wrapper( sessions.create, ) self.cancel = to_streamed_response_wrapper( sessions.cancel, ) class AsyncSessionsWithStreamingResponse: def __init__(self, sessions: AsyncSessions) -> None: self._sessions = sessions self.create = async_to_streamed_response_wrapper( sessions.create, ) self.cancel = async_to_streamed_response_wrapper( sessions.cancel, ) ================================================ FILE: src/openai/resources/beta/chatkit/threads.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Any, cast from typing_extensions import Literal import httpx from .... import _legacy_response from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ...._utils import maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ....pagination import SyncConversationCursorPage, AsyncConversationCursorPage from ...._base_client import AsyncPaginator, make_request_options from ....types.beta.chatkit import thread_list_params, thread_list_items_params from ....types.beta.chatkit.chatkit_thread import ChatKitThread from ....types.beta.chatkit.thread_delete_response import ThreadDeleteResponse from ....types.beta.chatkit.chatkit_thread_item_list import Data __all__ = ["Threads", "AsyncThreads"] class Threads(SyncAPIResource): @cached_property def with_raw_response(self) -> ThreadsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return ThreadsWithRawResponse(self) @cached_property def with_streaming_response(self) -> ThreadsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return ThreadsWithStreamingResponse(self) def retrieve( self, thread_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatKitThread: """ Retrieve a ChatKit thread by its identifier. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "chatkit_beta=v1", **(extra_headers or {})} return self._get( f"/chatkit/threads/{thread_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ChatKitThread, ) def list( self, *, after: str | Omit = omit, before: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncConversationCursorPage[ChatKitThread]: """ List ChatKit threads with optional pagination and user filters. Args: after: List items created after this thread item ID. Defaults to null for the first page. before: List items created before this thread item ID. Defaults to null for the newest results. limit: Maximum number of thread items to return. Defaults to 20. order: Sort order for results by creation time. Defaults to `desc`. user: Filter threads that belong to this user identifier. Defaults to null to return all users. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"OpenAI-Beta": "chatkit_beta=v1", **(extra_headers or {})} return self._get_api_list( "/chatkit/threads", page=SyncConversationCursorPage[ChatKitThread], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "limit": limit, "order": order, "user": user, }, thread_list_params.ThreadListParams, ), ), model=ChatKitThread, ) def delete( self, thread_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ThreadDeleteResponse: """ Delete a ChatKit thread along with its items and stored attachments. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "chatkit_beta=v1", **(extra_headers or {})} return self._delete( f"/chatkit/threads/{thread_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ThreadDeleteResponse, ) def list_items( self, thread_id: str, *, after: str | Omit = omit, before: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncConversationCursorPage[Data]: """ List items that belong to a ChatKit thread. Args: after: List items created after this thread item ID. Defaults to null for the first page. before: List items created before this thread item ID. Defaults to null for the newest results. limit: Maximum number of thread items to return. Defaults to 20. order: Sort order for results by creation time. Defaults to `desc`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "chatkit_beta=v1", **(extra_headers or {})} return self._get_api_list( f"/chatkit/threads/{thread_id}/items", page=SyncConversationCursorPage[Data], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "limit": limit, "order": order, }, thread_list_items_params.ThreadListItemsParams, ), ), model=cast(Any, Data), # Union types cannot be passed in as arguments in the type system ) class AsyncThreads(AsyncAPIResource): @cached_property def with_raw_response(self) -> AsyncThreadsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncThreadsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncThreadsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncThreadsWithStreamingResponse(self) async def retrieve( self, thread_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatKitThread: """ Retrieve a ChatKit thread by its identifier. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "chatkit_beta=v1", **(extra_headers or {})} return await self._get( f"/chatkit/threads/{thread_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ChatKitThread, ) def list( self, *, after: str | Omit = omit, before: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[ChatKitThread, AsyncConversationCursorPage[ChatKitThread]]: """ List ChatKit threads with optional pagination and user filters. Args: after: List items created after this thread item ID. Defaults to null for the first page. before: List items created before this thread item ID. Defaults to null for the newest results. limit: Maximum number of thread items to return. Defaults to 20. order: Sort order for results by creation time. Defaults to `desc`. user: Filter threads that belong to this user identifier. Defaults to null to return all users. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"OpenAI-Beta": "chatkit_beta=v1", **(extra_headers or {})} return self._get_api_list( "/chatkit/threads", page=AsyncConversationCursorPage[ChatKitThread], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "limit": limit, "order": order, "user": user, }, thread_list_params.ThreadListParams, ), ), model=ChatKitThread, ) async def delete( self, thread_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ThreadDeleteResponse: """ Delete a ChatKit thread along with its items and stored attachments. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "chatkit_beta=v1", **(extra_headers or {})} return await self._delete( f"/chatkit/threads/{thread_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ThreadDeleteResponse, ) def list_items( self, thread_id: str, *, after: str | Omit = omit, before: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[Data, AsyncConversationCursorPage[Data]]: """ List items that belong to a ChatKit thread. Args: after: List items created after this thread item ID. Defaults to null for the first page. before: List items created before this thread item ID. Defaults to null for the newest results. limit: Maximum number of thread items to return. Defaults to 20. order: Sort order for results by creation time. Defaults to `desc`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "chatkit_beta=v1", **(extra_headers or {})} return self._get_api_list( f"/chatkit/threads/{thread_id}/items", page=AsyncConversationCursorPage[Data], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "limit": limit, "order": order, }, thread_list_items_params.ThreadListItemsParams, ), ), model=cast(Any, Data), # Union types cannot be passed in as arguments in the type system ) class ThreadsWithRawResponse: def __init__(self, threads: Threads) -> None: self._threads = threads self.retrieve = _legacy_response.to_raw_response_wrapper( threads.retrieve, ) self.list = _legacy_response.to_raw_response_wrapper( threads.list, ) self.delete = _legacy_response.to_raw_response_wrapper( threads.delete, ) self.list_items = _legacy_response.to_raw_response_wrapper( threads.list_items, ) class AsyncThreadsWithRawResponse: def __init__(self, threads: AsyncThreads) -> None: self._threads = threads self.retrieve = _legacy_response.async_to_raw_response_wrapper( threads.retrieve, ) self.list = _legacy_response.async_to_raw_response_wrapper( threads.list, ) self.delete = _legacy_response.async_to_raw_response_wrapper( threads.delete, ) self.list_items = _legacy_response.async_to_raw_response_wrapper( threads.list_items, ) class ThreadsWithStreamingResponse: def __init__(self, threads: Threads) -> None: self._threads = threads self.retrieve = to_streamed_response_wrapper( threads.retrieve, ) self.list = to_streamed_response_wrapper( threads.list, ) self.delete = to_streamed_response_wrapper( threads.delete, ) self.list_items = to_streamed_response_wrapper( threads.list_items, ) class AsyncThreadsWithStreamingResponse: def __init__(self, threads: AsyncThreads) -> None: self._threads = threads self.retrieve = async_to_streamed_response_wrapper( threads.retrieve, ) self.list = async_to_streamed_response_wrapper( threads.list, ) self.delete = async_to_streamed_response_wrapper( threads.delete, ) self.list_items = async_to_streamed_response_wrapper( threads.list_items, ) ================================================ FILE: src/openai/resources/beta/realtime/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .realtime import ( Realtime, AsyncRealtime, RealtimeWithRawResponse, AsyncRealtimeWithRawResponse, RealtimeWithStreamingResponse, AsyncRealtimeWithStreamingResponse, ) from .sessions import ( Sessions, AsyncSessions, SessionsWithRawResponse, AsyncSessionsWithRawResponse, SessionsWithStreamingResponse, AsyncSessionsWithStreamingResponse, ) from .transcription_sessions import ( TranscriptionSessions, AsyncTranscriptionSessions, TranscriptionSessionsWithRawResponse, AsyncTranscriptionSessionsWithRawResponse, TranscriptionSessionsWithStreamingResponse, AsyncTranscriptionSessionsWithStreamingResponse, ) __all__ = [ "Sessions", "AsyncSessions", "SessionsWithRawResponse", "AsyncSessionsWithRawResponse", "SessionsWithStreamingResponse", "AsyncSessionsWithStreamingResponse", "TranscriptionSessions", "AsyncTranscriptionSessions", "TranscriptionSessionsWithRawResponse", "AsyncTranscriptionSessionsWithRawResponse", "TranscriptionSessionsWithStreamingResponse", "AsyncTranscriptionSessionsWithStreamingResponse", "Realtime", "AsyncRealtime", "RealtimeWithRawResponse", "AsyncRealtimeWithRawResponse", "RealtimeWithStreamingResponse", "AsyncRealtimeWithStreamingResponse", ] ================================================ FILE: src/openai/resources/beta/realtime/realtime.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import json import logging from types import TracebackType from typing import TYPE_CHECKING, Any, Iterator, cast from typing_extensions import AsyncIterator import httpx from pydantic import BaseModel from .sessions import ( Sessions, AsyncSessions, SessionsWithRawResponse, AsyncSessionsWithRawResponse, SessionsWithStreamingResponse, AsyncSessionsWithStreamingResponse, ) from ...._types import NOT_GIVEN, Query, Headers, NotGiven from ...._utils import ( is_azure_client, maybe_transform, strip_not_given, async_maybe_transform, is_async_azure_client, ) from ...._compat import cached_property from ...._models import construct_type_unchecked from ...._resource import SyncAPIResource, AsyncAPIResource from ...._exceptions import OpenAIError from ...._base_client import _merge_mappings from ....types.beta.realtime import ( session_update_event_param, response_create_event_param, transcription_session_update_param, ) from .transcription_sessions import ( TranscriptionSessions, AsyncTranscriptionSessions, TranscriptionSessionsWithRawResponse, AsyncTranscriptionSessionsWithRawResponse, TranscriptionSessionsWithStreamingResponse, AsyncTranscriptionSessionsWithStreamingResponse, ) from ....types.websocket_connection_options import WebsocketConnectionOptions from ....types.beta.realtime.realtime_client_event import RealtimeClientEvent from ....types.beta.realtime.realtime_server_event import RealtimeServerEvent from ....types.beta.realtime.conversation_item_param import ConversationItemParam from ....types.beta.realtime.realtime_client_event_param import RealtimeClientEventParam if TYPE_CHECKING: from websockets.sync.client import ClientConnection as WebsocketConnection from websockets.asyncio.client import ClientConnection as AsyncWebsocketConnection from ...._client import OpenAI, AsyncOpenAI __all__ = ["Realtime", "AsyncRealtime"] log: logging.Logger = logging.getLogger(__name__) class Realtime(SyncAPIResource): @cached_property def sessions(self) -> Sessions: return Sessions(self._client) @cached_property def transcription_sessions(self) -> TranscriptionSessions: return TranscriptionSessions(self._client) @cached_property def with_raw_response(self) -> RealtimeWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return RealtimeWithRawResponse(self) @cached_property def with_streaming_response(self) -> RealtimeWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return RealtimeWithStreamingResponse(self) def connect( self, *, model: str, extra_query: Query = {}, extra_headers: Headers = {}, websocket_connection_options: WebsocketConnectionOptions = {}, ) -> RealtimeConnectionManager: """ The Realtime API enables you to build low-latency, multi-modal conversational experiences. It currently supports text and audio as both input and output, as well as function calling. Some notable benefits of the API include: - Native speech-to-speech: Skipping an intermediate text format means low latency and nuanced output. - Natural, steerable voices: The models have natural inflection and can laugh, whisper, and adhere to tone direction. - Simultaneous multimodal output: Text is useful for moderation; faster-than-realtime audio ensures stable playback. The Realtime API is a stateful, event-based API that communicates over a WebSocket. """ return RealtimeConnectionManager( client=self._client, extra_query=extra_query, extra_headers=extra_headers, websocket_connection_options=websocket_connection_options, model=model, ) class AsyncRealtime(AsyncAPIResource): @cached_property def sessions(self) -> AsyncSessions: return AsyncSessions(self._client) @cached_property def transcription_sessions(self) -> AsyncTranscriptionSessions: return AsyncTranscriptionSessions(self._client) @cached_property def with_raw_response(self) -> AsyncRealtimeWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncRealtimeWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncRealtimeWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncRealtimeWithStreamingResponse(self) def connect( self, *, model: str, extra_query: Query = {}, extra_headers: Headers = {}, websocket_connection_options: WebsocketConnectionOptions = {}, ) -> AsyncRealtimeConnectionManager: """ The Realtime API enables you to build low-latency, multi-modal conversational experiences. It currently supports text and audio as both input and output, as well as function calling. Some notable benefits of the API include: - Native speech-to-speech: Skipping an intermediate text format means low latency and nuanced output. - Natural, steerable voices: The models have natural inflection and can laugh, whisper, and adhere to tone direction. - Simultaneous multimodal output: Text is useful for moderation; faster-than-realtime audio ensures stable playback. The Realtime API is a stateful, event-based API that communicates over a WebSocket. """ return AsyncRealtimeConnectionManager( client=self._client, extra_query=extra_query, extra_headers=extra_headers, websocket_connection_options=websocket_connection_options, model=model, ) class RealtimeWithRawResponse: def __init__(self, realtime: Realtime) -> None: self._realtime = realtime @cached_property def sessions(self) -> SessionsWithRawResponse: return SessionsWithRawResponse(self._realtime.sessions) @cached_property def transcription_sessions(self) -> TranscriptionSessionsWithRawResponse: return TranscriptionSessionsWithRawResponse(self._realtime.transcription_sessions) class AsyncRealtimeWithRawResponse: def __init__(self, realtime: AsyncRealtime) -> None: self._realtime = realtime @cached_property def sessions(self) -> AsyncSessionsWithRawResponse: return AsyncSessionsWithRawResponse(self._realtime.sessions) @cached_property def transcription_sessions(self) -> AsyncTranscriptionSessionsWithRawResponse: return AsyncTranscriptionSessionsWithRawResponse(self._realtime.transcription_sessions) class RealtimeWithStreamingResponse: def __init__(self, realtime: Realtime) -> None: self._realtime = realtime @cached_property def sessions(self) -> SessionsWithStreamingResponse: return SessionsWithStreamingResponse(self._realtime.sessions) @cached_property def transcription_sessions(self) -> TranscriptionSessionsWithStreamingResponse: return TranscriptionSessionsWithStreamingResponse(self._realtime.transcription_sessions) class AsyncRealtimeWithStreamingResponse: def __init__(self, realtime: AsyncRealtime) -> None: self._realtime = realtime @cached_property def sessions(self) -> AsyncSessionsWithStreamingResponse: return AsyncSessionsWithStreamingResponse(self._realtime.sessions) @cached_property def transcription_sessions(self) -> AsyncTranscriptionSessionsWithStreamingResponse: return AsyncTranscriptionSessionsWithStreamingResponse(self._realtime.transcription_sessions) class AsyncRealtimeConnection: """Represents a live websocket connection to the Realtime API""" session: AsyncRealtimeSessionResource response: AsyncRealtimeResponseResource input_audio_buffer: AsyncRealtimeInputAudioBufferResource conversation: AsyncRealtimeConversationResource output_audio_buffer: AsyncRealtimeOutputAudioBufferResource transcription_session: AsyncRealtimeTranscriptionSessionResource _connection: AsyncWebsocketConnection def __init__(self, connection: AsyncWebsocketConnection) -> None: self._connection = connection self.session = AsyncRealtimeSessionResource(self) self.response = AsyncRealtimeResponseResource(self) self.input_audio_buffer = AsyncRealtimeInputAudioBufferResource(self) self.conversation = AsyncRealtimeConversationResource(self) self.output_audio_buffer = AsyncRealtimeOutputAudioBufferResource(self) self.transcription_session = AsyncRealtimeTranscriptionSessionResource(self) async def __aiter__(self) -> AsyncIterator[RealtimeServerEvent]: """ An infinite-iterator that will continue to yield events until the connection is closed. """ from websockets.exceptions import ConnectionClosedOK try: while True: yield await self.recv() except ConnectionClosedOK: return async def recv(self) -> RealtimeServerEvent: """ Receive the next message from the connection and parses it into a `RealtimeServerEvent` object. Canceling this method is safe. There's no risk of losing data. """ return self.parse_event(await self.recv_bytes()) async def recv_bytes(self) -> bytes: """Receive the next message from the connection as raw bytes. Canceling this method is safe. There's no risk of losing data. If you want to parse the message into a `RealtimeServerEvent` object like `.recv()` does, then you can call `.parse_event(data)`. """ message = await self._connection.recv(decode=False) log.debug(f"Received websocket message: %s", message) return message async def send(self, event: RealtimeClientEvent | RealtimeClientEventParam) -> None: data = ( event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) if isinstance(event, BaseModel) else json.dumps(await async_maybe_transform(event, RealtimeClientEventParam)) ) await self._connection.send(data) async def close(self, *, code: int = 1000, reason: str = "") -> None: await self._connection.close(code=code, reason=reason) def parse_event(self, data: str | bytes) -> RealtimeServerEvent: """ Converts a raw `str` or `bytes` message into a `RealtimeServerEvent` object. This is helpful if you're using `.recv_bytes()`. """ return cast( RealtimeServerEvent, construct_type_unchecked(value=json.loads(data), type_=cast(Any, RealtimeServerEvent)) ) class AsyncRealtimeConnectionManager: """ Context manager over a `AsyncRealtimeConnection` that is returned by `beta.realtime.connect()` This context manager ensures that the connection will be closed when it exits. --- Note that if your application doesn't work well with the context manager approach then you can call the `.enter()` method directly to initiate a connection. **Warning**: You must remember to close the connection with `.close()`. ```py connection = await client.beta.realtime.connect(...).enter() # ... await connection.close() ``` """ def __init__( self, *, client: AsyncOpenAI, model: str, extra_query: Query, extra_headers: Headers, websocket_connection_options: WebsocketConnectionOptions, ) -> None: self.__client = client self.__model = model self.__connection: AsyncRealtimeConnection | None = None self.__extra_query = extra_query self.__extra_headers = extra_headers self.__websocket_connection_options = websocket_connection_options async def __aenter__(self) -> AsyncRealtimeConnection: """ 👋 If your application doesn't work well with the context manager approach then you can call this method directly to initiate a connection. **Warning**: You must remember to close the connection with `.close()`. ```py connection = await client.beta.realtime.connect(...).enter() # ... await connection.close() ``` """ try: from websockets.asyncio.client import connect except ImportError as exc: raise OpenAIError("You need to install `openai[realtime]` to use this method") from exc extra_query = self.__extra_query await self.__client._refresh_api_key() auth_headers = self.__client.auth_headers if is_async_azure_client(self.__client): url, auth_headers = await self.__client._configure_realtime(self.__model, extra_query) else: url = self._prepare_url().copy_with( params={ **self.__client.base_url.params, "model": self.__model, **extra_query, }, ) log.debug("Connecting to %s", url) if self.__websocket_connection_options: log.debug("Connection options: %s", self.__websocket_connection_options) self.__connection = AsyncRealtimeConnection( await connect( str(url), user_agent_header=self.__client.user_agent, additional_headers=_merge_mappings( { **auth_headers, "OpenAI-Beta": "realtime=v1", }, self.__extra_headers, ), **self.__websocket_connection_options, ) ) return self.__connection enter = __aenter__ def _prepare_url(self) -> httpx.URL: if self.__client.websocket_base_url is not None: base_url = httpx.URL(self.__client.websocket_base_url) else: base_url = self.__client._base_url.copy_with(scheme="wss") merge_raw_path = base_url.raw_path.rstrip(b"/") + b"/realtime" return base_url.copy_with(raw_path=merge_raw_path) async def __aexit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None ) -> None: if self.__connection is not None: await self.__connection.close() class RealtimeConnection: """Represents a live websocket connection to the Realtime API""" session: RealtimeSessionResource response: RealtimeResponseResource input_audio_buffer: RealtimeInputAudioBufferResource conversation: RealtimeConversationResource output_audio_buffer: RealtimeOutputAudioBufferResource transcription_session: RealtimeTranscriptionSessionResource _connection: WebsocketConnection def __init__(self, connection: WebsocketConnection) -> None: self._connection = connection self.session = RealtimeSessionResource(self) self.response = RealtimeResponseResource(self) self.input_audio_buffer = RealtimeInputAudioBufferResource(self) self.conversation = RealtimeConversationResource(self) self.output_audio_buffer = RealtimeOutputAudioBufferResource(self) self.transcription_session = RealtimeTranscriptionSessionResource(self) def __iter__(self) -> Iterator[RealtimeServerEvent]: """ An infinite-iterator that will continue to yield events until the connection is closed. """ from websockets.exceptions import ConnectionClosedOK try: while True: yield self.recv() except ConnectionClosedOK: return def recv(self) -> RealtimeServerEvent: """ Receive the next message from the connection and parses it into a `RealtimeServerEvent` object. Canceling this method is safe. There's no risk of losing data. """ return self.parse_event(self.recv_bytes()) def recv_bytes(self) -> bytes: """Receive the next message from the connection as raw bytes. Canceling this method is safe. There's no risk of losing data. If you want to parse the message into a `RealtimeServerEvent` object like `.recv()` does, then you can call `.parse_event(data)`. """ message = self._connection.recv(decode=False) log.debug(f"Received websocket message: %s", message) return message def send(self, event: RealtimeClientEvent | RealtimeClientEventParam) -> None: data = ( event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) if isinstance(event, BaseModel) else json.dumps(maybe_transform(event, RealtimeClientEventParam)) ) self._connection.send(data) def close(self, *, code: int = 1000, reason: str = "") -> None: self._connection.close(code=code, reason=reason) def parse_event(self, data: str | bytes) -> RealtimeServerEvent: """ Converts a raw `str` or `bytes` message into a `RealtimeServerEvent` object. This is helpful if you're using `.recv_bytes()`. """ return cast( RealtimeServerEvent, construct_type_unchecked(value=json.loads(data), type_=cast(Any, RealtimeServerEvent)) ) class RealtimeConnectionManager: """ Context manager over a `RealtimeConnection` that is returned by `beta.realtime.connect()` This context manager ensures that the connection will be closed when it exits. --- Note that if your application doesn't work well with the context manager approach then you can call the `.enter()` method directly to initiate a connection. **Warning**: You must remember to close the connection with `.close()`. ```py connection = client.beta.realtime.connect(...).enter() # ... connection.close() ``` """ def __init__( self, *, client: OpenAI, model: str, extra_query: Query, extra_headers: Headers, websocket_connection_options: WebsocketConnectionOptions, ) -> None: self.__client = client self.__model = model self.__connection: RealtimeConnection | None = None self.__extra_query = extra_query self.__extra_headers = extra_headers self.__websocket_connection_options = websocket_connection_options def __enter__(self) -> RealtimeConnection: """ 👋 If your application doesn't work well with the context manager approach then you can call this method directly to initiate a connection. **Warning**: You must remember to close the connection with `.close()`. ```py connection = client.beta.realtime.connect(...).enter() # ... connection.close() ``` """ try: from websockets.sync.client import connect except ImportError as exc: raise OpenAIError("You need to install `openai[realtime]` to use this method") from exc extra_query = self.__extra_query self.__client._refresh_api_key() auth_headers = self.__client.auth_headers if is_azure_client(self.__client): url, auth_headers = self.__client._configure_realtime(self.__model, extra_query) else: url = self._prepare_url().copy_with( params={ **self.__client.base_url.params, "model": self.__model, **extra_query, }, ) log.debug("Connecting to %s", url) if self.__websocket_connection_options: log.debug("Connection options: %s", self.__websocket_connection_options) self.__connection = RealtimeConnection( connect( str(url), user_agent_header=self.__client.user_agent, additional_headers=_merge_mappings( { **auth_headers, "OpenAI-Beta": "realtime=v1", }, self.__extra_headers, ), **self.__websocket_connection_options, ) ) return self.__connection enter = __enter__ def _prepare_url(self) -> httpx.URL: if self.__client.websocket_base_url is not None: base_url = httpx.URL(self.__client.websocket_base_url) else: base_url = self.__client._base_url.copy_with(scheme="wss") merge_raw_path = base_url.raw_path.rstrip(b"/") + b"/realtime" return base_url.copy_with(raw_path=merge_raw_path) def __exit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None ) -> None: if self.__connection is not None: self.__connection.close() class BaseRealtimeConnectionResource: def __init__(self, connection: RealtimeConnection) -> None: self._connection = connection class RealtimeSessionResource(BaseRealtimeConnectionResource): def update(self, *, session: session_update_event_param.Session, event_id: str | NotGiven = NOT_GIVEN) -> None: """ Send this event to update the session’s default configuration. The client may send this event at any time to update any field, except for `voice`. However, note that once a session has been initialized with a particular `model`, it can’t be changed to another model using `session.update`. When the server receives a `session.update`, it will respond with a `session.updated` event showing the full, effective configuration. Only the fields that are present are updated. To clear a field like `instructions`, pass an empty string. """ self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "session.update", "session": session, "event_id": event_id}), ) ) class RealtimeResponseResource(BaseRealtimeConnectionResource): def create( self, *, event_id: str | NotGiven = NOT_GIVEN, response: response_create_event_param.Response | NotGiven = NOT_GIVEN, ) -> None: """ This event instructs the server to create a Response, which means triggering model inference. When in Server VAD mode, the server will create Responses automatically. A Response will include at least one Item, and may have two, in which case the second will be a function call. These Items will be appended to the conversation history. The server will respond with a `response.created` event, events for Items and content created, and finally a `response.done` event to indicate the Response is complete. The `response.create` event includes inference configuration like `instructions`, and `temperature`. These fields will override the Session's configuration for this Response only. """ self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "response.create", "event_id": event_id, "response": response}), ) ) def cancel(self, *, event_id: str | NotGiven = NOT_GIVEN, response_id: str | NotGiven = NOT_GIVEN) -> None: """Send this event to cancel an in-progress response. The server will respond with a `response.done` event with a status of `response.status=cancelled`. If there is no response to cancel, the server will respond with an error. """ self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "response.cancel", "event_id": event_id, "response_id": response_id}), ) ) class RealtimeInputAudioBufferResource(BaseRealtimeConnectionResource): def clear(self, *, event_id: str | NotGiven = NOT_GIVEN) -> None: """Send this event to clear the audio bytes in the buffer. The server will respond with an `input_audio_buffer.cleared` event. """ self._connection.send( cast(RealtimeClientEventParam, strip_not_given({"type": "input_audio_buffer.clear", "event_id": event_id})) ) def commit(self, *, event_id: str | NotGiven = NOT_GIVEN) -> None: """ Send this event to commit the user input audio buffer, which will create a new user message item in the conversation. This event will produce an error if the input audio buffer is empty. When in Server VAD mode, the client does not need to send this event, the server will commit the audio buffer automatically. Committing the input audio buffer will trigger input audio transcription (if enabled in session configuration), but it will not create a response from the model. The server will respond with an `input_audio_buffer.committed` event. """ self._connection.send( cast(RealtimeClientEventParam, strip_not_given({"type": "input_audio_buffer.commit", "event_id": event_id})) ) def append(self, *, audio: str, event_id: str | NotGiven = NOT_GIVEN) -> None: """Send this event to append audio bytes to the input audio buffer. The audio buffer is temporary storage you can write to and later commit. In Server VAD mode, the audio buffer is used to detect speech and the server will decide when to commit. When Server VAD is disabled, you must commit the audio buffer manually. The client may choose how much audio to place in each event up to a maximum of 15 MiB, for example streaming smaller chunks from the client may allow the VAD to be more responsive. Unlike made other client events, the server will not send a confirmation response to this event. """ self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "input_audio_buffer.append", "audio": audio, "event_id": event_id}), ) ) class RealtimeConversationResource(BaseRealtimeConnectionResource): @cached_property def item(self) -> RealtimeConversationItemResource: return RealtimeConversationItemResource(self._connection) class RealtimeConversationItemResource(BaseRealtimeConnectionResource): def delete(self, *, item_id: str, event_id: str | NotGiven = NOT_GIVEN) -> None: """Send this event when you want to remove any item from the conversation history. The server will respond with a `conversation.item.deleted` event, unless the item does not exist in the conversation history, in which case the server will respond with an error. """ self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "conversation.item.delete", "item_id": item_id, "event_id": event_id}), ) ) def create( self, *, item: ConversationItemParam, event_id: str | NotGiven = NOT_GIVEN, previous_item_id: str | NotGiven = NOT_GIVEN, ) -> None: """ Add a new Item to the Conversation's context, including messages, function calls, and function call responses. This event can be used both to populate a "history" of the conversation and to add new items mid-stream, but has the current limitation that it cannot populate assistant audio messages. If successful, the server will respond with a `conversation.item.created` event, otherwise an `error` event will be sent. """ self._connection.send( cast( RealtimeClientEventParam, strip_not_given( { "type": "conversation.item.create", "item": item, "event_id": event_id, "previous_item_id": previous_item_id, } ), ) ) def truncate( self, *, audio_end_ms: int, content_index: int, item_id: str, event_id: str | NotGiven = NOT_GIVEN ) -> None: """Send this event to truncate a previous assistant message’s audio. The server will produce audio faster than realtime, so this event is useful when the user interrupts to truncate audio that has already been sent to the client but not yet played. This will synchronize the server's understanding of the audio with the client's playback. Truncating audio will delete the server-side text transcript to ensure there is not text in the context that hasn't been heard by the user. If successful, the server will respond with a `conversation.item.truncated` event. """ self._connection.send( cast( RealtimeClientEventParam, strip_not_given( { "type": "conversation.item.truncate", "audio_end_ms": audio_end_ms, "content_index": content_index, "item_id": item_id, "event_id": event_id, } ), ) ) def retrieve(self, *, item_id: str, event_id: str | NotGiven = NOT_GIVEN) -> None: """ Send this event when you want to retrieve the server's representation of a specific item in the conversation history. This is useful, for example, to inspect user audio after noise cancellation and VAD. The server will respond with a `conversation.item.retrieved` event, unless the item does not exist in the conversation history, in which case the server will respond with an error. """ self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "conversation.item.retrieve", "item_id": item_id, "event_id": event_id}), ) ) class RealtimeOutputAudioBufferResource(BaseRealtimeConnectionResource): def clear(self, *, event_id: str | NotGiven = NOT_GIVEN) -> None: """**WebRTC Only:** Emit to cut off the current audio response. This will trigger the server to stop generating audio and emit a `output_audio_buffer.cleared` event. This event should be preceded by a `response.cancel` client event to stop the generation of the current response. [Learn more](https://platform.openai.com/docs/guides/realtime-conversations#client-and-server-events-for-audio-in-webrtc). """ self._connection.send( cast(RealtimeClientEventParam, strip_not_given({"type": "output_audio_buffer.clear", "event_id": event_id})) ) class RealtimeTranscriptionSessionResource(BaseRealtimeConnectionResource): def update( self, *, session: transcription_session_update_param.Session, event_id: str | NotGiven = NOT_GIVEN ) -> None: """Send this event to update a transcription session.""" self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "transcription_session.update", "session": session, "event_id": event_id}), ) ) class BaseAsyncRealtimeConnectionResource: def __init__(self, connection: AsyncRealtimeConnection) -> None: self._connection = connection class AsyncRealtimeSessionResource(BaseAsyncRealtimeConnectionResource): async def update( self, *, session: session_update_event_param.Session, event_id: str | NotGiven = NOT_GIVEN ) -> None: """ Send this event to update the session’s default configuration. The client may send this event at any time to update any field, except for `voice`. However, note that once a session has been initialized with a particular `model`, it can’t be changed to another model using `session.update`. When the server receives a `session.update`, it will respond with a `session.updated` event showing the full, effective configuration. Only the fields that are present are updated. To clear a field like `instructions`, pass an empty string. """ await self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "session.update", "session": session, "event_id": event_id}), ) ) class AsyncRealtimeResponseResource(BaseAsyncRealtimeConnectionResource): async def create( self, *, event_id: str | NotGiven = NOT_GIVEN, response: response_create_event_param.Response | NotGiven = NOT_GIVEN, ) -> None: """ This event instructs the server to create a Response, which means triggering model inference. When in Server VAD mode, the server will create Responses automatically. A Response will include at least one Item, and may have two, in which case the second will be a function call. These Items will be appended to the conversation history. The server will respond with a `response.created` event, events for Items and content created, and finally a `response.done` event to indicate the Response is complete. The `response.create` event includes inference configuration like `instructions`, and `temperature`. These fields will override the Session's configuration for this Response only. """ await self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "response.create", "event_id": event_id, "response": response}), ) ) async def cancel(self, *, event_id: str | NotGiven = NOT_GIVEN, response_id: str | NotGiven = NOT_GIVEN) -> None: """Send this event to cancel an in-progress response. The server will respond with a `response.done` event with a status of `response.status=cancelled`. If there is no response to cancel, the server will respond with an error. """ await self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "response.cancel", "event_id": event_id, "response_id": response_id}), ) ) class AsyncRealtimeInputAudioBufferResource(BaseAsyncRealtimeConnectionResource): async def clear(self, *, event_id: str | NotGiven = NOT_GIVEN) -> None: """Send this event to clear the audio bytes in the buffer. The server will respond with an `input_audio_buffer.cleared` event. """ await self._connection.send( cast(RealtimeClientEventParam, strip_not_given({"type": "input_audio_buffer.clear", "event_id": event_id})) ) async def commit(self, *, event_id: str | NotGiven = NOT_GIVEN) -> None: """ Send this event to commit the user input audio buffer, which will create a new user message item in the conversation. This event will produce an error if the input audio buffer is empty. When in Server VAD mode, the client does not need to send this event, the server will commit the audio buffer automatically. Committing the input audio buffer will trigger input audio transcription (if enabled in session configuration), but it will not create a response from the model. The server will respond with an `input_audio_buffer.committed` event. """ await self._connection.send( cast(RealtimeClientEventParam, strip_not_given({"type": "input_audio_buffer.commit", "event_id": event_id})) ) async def append(self, *, audio: str, event_id: str | NotGiven = NOT_GIVEN) -> None: """Send this event to append audio bytes to the input audio buffer. The audio buffer is temporary storage you can write to and later commit. In Server VAD mode, the audio buffer is used to detect speech and the server will decide when to commit. When Server VAD is disabled, you must commit the audio buffer manually. The client may choose how much audio to place in each event up to a maximum of 15 MiB, for example streaming smaller chunks from the client may allow the VAD to be more responsive. Unlike made other client events, the server will not send a confirmation response to this event. """ await self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "input_audio_buffer.append", "audio": audio, "event_id": event_id}), ) ) class AsyncRealtimeConversationResource(BaseAsyncRealtimeConnectionResource): @cached_property def item(self) -> AsyncRealtimeConversationItemResource: return AsyncRealtimeConversationItemResource(self._connection) class AsyncRealtimeConversationItemResource(BaseAsyncRealtimeConnectionResource): async def delete(self, *, item_id: str, event_id: str | NotGiven = NOT_GIVEN) -> None: """Send this event when you want to remove any item from the conversation history. The server will respond with a `conversation.item.deleted` event, unless the item does not exist in the conversation history, in which case the server will respond with an error. """ await self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "conversation.item.delete", "item_id": item_id, "event_id": event_id}), ) ) async def create( self, *, item: ConversationItemParam, event_id: str | NotGiven = NOT_GIVEN, previous_item_id: str | NotGiven = NOT_GIVEN, ) -> None: """ Add a new Item to the Conversation's context, including messages, function calls, and function call responses. This event can be used both to populate a "history" of the conversation and to add new items mid-stream, but has the current limitation that it cannot populate assistant audio messages. If successful, the server will respond with a `conversation.item.created` event, otherwise an `error` event will be sent. """ await self._connection.send( cast( RealtimeClientEventParam, strip_not_given( { "type": "conversation.item.create", "item": item, "event_id": event_id, "previous_item_id": previous_item_id, } ), ) ) async def truncate( self, *, audio_end_ms: int, content_index: int, item_id: str, event_id: str | NotGiven = NOT_GIVEN ) -> None: """Send this event to truncate a previous assistant message’s audio. The server will produce audio faster than realtime, so this event is useful when the user interrupts to truncate audio that has already been sent to the client but not yet played. This will synchronize the server's understanding of the audio with the client's playback. Truncating audio will delete the server-side text transcript to ensure there is not text in the context that hasn't been heard by the user. If successful, the server will respond with a `conversation.item.truncated` event. """ await self._connection.send( cast( RealtimeClientEventParam, strip_not_given( { "type": "conversation.item.truncate", "audio_end_ms": audio_end_ms, "content_index": content_index, "item_id": item_id, "event_id": event_id, } ), ) ) async def retrieve(self, *, item_id: str, event_id: str | NotGiven = NOT_GIVEN) -> None: """ Send this event when you want to retrieve the server's representation of a specific item in the conversation history. This is useful, for example, to inspect user audio after noise cancellation and VAD. The server will respond with a `conversation.item.retrieved` event, unless the item does not exist in the conversation history, in which case the server will respond with an error. """ await self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "conversation.item.retrieve", "item_id": item_id, "event_id": event_id}), ) ) class AsyncRealtimeOutputAudioBufferResource(BaseAsyncRealtimeConnectionResource): async def clear(self, *, event_id: str | NotGiven = NOT_GIVEN) -> None: """**WebRTC Only:** Emit to cut off the current audio response. This will trigger the server to stop generating audio and emit a `output_audio_buffer.cleared` event. This event should be preceded by a `response.cancel` client event to stop the generation of the current response. [Learn more](https://platform.openai.com/docs/guides/realtime-conversations#client-and-server-events-for-audio-in-webrtc). """ await self._connection.send( cast(RealtimeClientEventParam, strip_not_given({"type": "output_audio_buffer.clear", "event_id": event_id})) ) class AsyncRealtimeTranscriptionSessionResource(BaseAsyncRealtimeConnectionResource): async def update( self, *, session: transcription_session_update_param.Session, event_id: str | NotGiven = NOT_GIVEN ) -> None: """Send this event to update a transcription session.""" await self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "transcription_session.update", "session": session, "event_id": event_id}), ) ) ================================================ FILE: src/openai/resources/beta/realtime/sessions.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List, Union, Iterable from typing_extensions import Literal import httpx from .... import _legacy_response from ...._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ...._utils import maybe_transform, async_maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ...._base_client import make_request_options from ....types.beta.realtime import session_create_params from ....types.beta.realtime.session_create_response import SessionCreateResponse __all__ = ["Sessions", "AsyncSessions"] class Sessions(SyncAPIResource): @cached_property def with_raw_response(self) -> SessionsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return SessionsWithRawResponse(self) @cached_property def with_streaming_response(self) -> SessionsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return SessionsWithStreamingResponse(self) def create( self, *, client_secret: session_create_params.ClientSecret | NotGiven = NOT_GIVEN, input_audio_format: Literal["pcm16", "g711_ulaw", "g711_alaw"] | NotGiven = NOT_GIVEN, input_audio_noise_reduction: session_create_params.InputAudioNoiseReduction | NotGiven = NOT_GIVEN, input_audio_transcription: session_create_params.InputAudioTranscription | NotGiven = NOT_GIVEN, instructions: str | NotGiven = NOT_GIVEN, max_response_output_tokens: Union[int, Literal["inf"]] | NotGiven = NOT_GIVEN, modalities: List[Literal["text", "audio"]] | NotGiven = NOT_GIVEN, model: Literal[ "gpt-realtime", "gpt-realtime-2025-08-28", "gpt-4o-realtime-preview", "gpt-4o-realtime-preview-2024-10-01", "gpt-4o-realtime-preview-2024-12-17", "gpt-4o-realtime-preview-2025-06-03", "gpt-4o-mini-realtime-preview", "gpt-4o-mini-realtime-preview-2024-12-17", ] | NotGiven = NOT_GIVEN, output_audio_format: Literal["pcm16", "g711_ulaw", "g711_alaw"] | NotGiven = NOT_GIVEN, speed: float | NotGiven = NOT_GIVEN, temperature: float | NotGiven = NOT_GIVEN, tool_choice: str | NotGiven = NOT_GIVEN, tools: Iterable[session_create_params.Tool] | NotGiven = NOT_GIVEN, tracing: session_create_params.Tracing | NotGiven = NOT_GIVEN, turn_detection: session_create_params.TurnDetection | NotGiven = NOT_GIVEN, voice: Union[str, Literal["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse"]] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SessionCreateResponse: """ Create an ephemeral API token for use in client-side applications with the Realtime API. Can be configured with the same session parameters as the `session.update` client event. It responds with a session object, plus a `client_secret` key which contains a usable ephemeral API token that can be used to authenticate browser clients for the Realtime API. Args: client_secret: Configuration options for the generated client secret. input_audio_format: The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`. For `pcm16`, input audio must be 16-bit PCM at a 24kHz sample rate, single channel (mono), and little-endian byte order. input_audio_noise_reduction: Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. input_audio_transcription: Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](https://platform.openai.com/docs/api-reference/audio/createTranscription) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service. instructions: The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. "be extremely succinct", "act friendly", "here are examples of good responses") and on audio behavior (e.g. "talk quickly", "inject emotion into your voice", "laugh frequently"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior. Note that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session. max_response_output_tokens: Maximum number of output tokens for a single assistant response, inclusive of tool calls. Provide an integer between 1 and 4096 to limit output tokens, or `inf` for the maximum available tokens for a given model. Defaults to `inf`. modalities: The set of modalities the model can respond with. To disable audio, set this to ["text"]. model: The Realtime model used for this session. output_audio_format: The format of output audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`. For `pcm16`, output audio is sampled at a rate of 24kHz. speed: The speed of the model's spoken response. 1.0 is the default speed. 0.25 is the minimum speed. 1.5 is the maximum speed. This value can only be changed in between model turns, not while a response is in progress. temperature: Sampling temperature for the model, limited to [0.6, 1.2]. For audio models a temperature of 0.8 is highly recommended for best performance. tool_choice: How the model chooses tools. Options are `auto`, `none`, `required`, or specify a function. tools: Tools (functions) available to the model. tracing: Configuration options for tracing. Set to null to disable tracing. Once tracing is enabled for a session, the configuration cannot be modified. `auto` will create a trace for the session with default values for the workflow name, group id, and metadata. turn_detection: Configuration for turn detection, ether Server VAD or Semantic VAD. This can be set to `null` to turn off, in which case the client must manually trigger model response. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. Semantic VAD is more advanced and uses a turn detection model (in conjunction with VAD) to semantically estimate whether the user has finished speaking, then dynamically sets a timeout based on this probability. For example, if user audio trails off with "uhhm", the model will score a low probability of turn end and wait longer for the user to continue speaking. This can be useful for more natural conversations, but may have a higher latency. voice: The voice the model uses to respond. Voice cannot be changed during the session once the model has responded with audio at least once. Current voice options are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, and `verse`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._post( "/realtime/sessions", body=maybe_transform( { "client_secret": client_secret, "input_audio_format": input_audio_format, "input_audio_noise_reduction": input_audio_noise_reduction, "input_audio_transcription": input_audio_transcription, "instructions": instructions, "max_response_output_tokens": max_response_output_tokens, "modalities": modalities, "model": model, "output_audio_format": output_audio_format, "speed": speed, "temperature": temperature, "tool_choice": tool_choice, "tools": tools, "tracing": tracing, "turn_detection": turn_detection, "voice": voice, }, session_create_params.SessionCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=SessionCreateResponse, ) class AsyncSessions(AsyncAPIResource): @cached_property def with_raw_response(self) -> AsyncSessionsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncSessionsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncSessionsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncSessionsWithStreamingResponse(self) async def create( self, *, client_secret: session_create_params.ClientSecret | NotGiven = NOT_GIVEN, input_audio_format: Literal["pcm16", "g711_ulaw", "g711_alaw"] | NotGiven = NOT_GIVEN, input_audio_noise_reduction: session_create_params.InputAudioNoiseReduction | NotGiven = NOT_GIVEN, input_audio_transcription: session_create_params.InputAudioTranscription | NotGiven = NOT_GIVEN, instructions: str | NotGiven = NOT_GIVEN, max_response_output_tokens: Union[int, Literal["inf"]] | NotGiven = NOT_GIVEN, modalities: List[Literal["text", "audio"]] | NotGiven = NOT_GIVEN, model: Literal[ "gpt-realtime", "gpt-realtime-2025-08-28", "gpt-4o-realtime-preview", "gpt-4o-realtime-preview-2024-10-01", "gpt-4o-realtime-preview-2024-12-17", "gpt-4o-realtime-preview-2025-06-03", "gpt-4o-mini-realtime-preview", "gpt-4o-mini-realtime-preview-2024-12-17", ] | NotGiven = NOT_GIVEN, output_audio_format: Literal["pcm16", "g711_ulaw", "g711_alaw"] | NotGiven = NOT_GIVEN, speed: float | NotGiven = NOT_GIVEN, temperature: float | NotGiven = NOT_GIVEN, tool_choice: str | NotGiven = NOT_GIVEN, tools: Iterable[session_create_params.Tool] | NotGiven = NOT_GIVEN, tracing: session_create_params.Tracing | NotGiven = NOT_GIVEN, turn_detection: session_create_params.TurnDetection | NotGiven = NOT_GIVEN, voice: Union[str, Literal["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse"]] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SessionCreateResponse: """ Create an ephemeral API token for use in client-side applications with the Realtime API. Can be configured with the same session parameters as the `session.update` client event. It responds with a session object, plus a `client_secret` key which contains a usable ephemeral API token that can be used to authenticate browser clients for the Realtime API. Args: client_secret: Configuration options for the generated client secret. input_audio_format: The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`. For `pcm16`, input audio must be 16-bit PCM at a 24kHz sample rate, single channel (mono), and little-endian byte order. input_audio_noise_reduction: Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. input_audio_transcription: Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](https://platform.openai.com/docs/api-reference/audio/createTranscription) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service. instructions: The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. "be extremely succinct", "act friendly", "here are examples of good responses") and on audio behavior (e.g. "talk quickly", "inject emotion into your voice", "laugh frequently"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior. Note that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session. max_response_output_tokens: Maximum number of output tokens for a single assistant response, inclusive of tool calls. Provide an integer between 1 and 4096 to limit output tokens, or `inf` for the maximum available tokens for a given model. Defaults to `inf`. modalities: The set of modalities the model can respond with. To disable audio, set this to ["text"]. model: The Realtime model used for this session. output_audio_format: The format of output audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`. For `pcm16`, output audio is sampled at a rate of 24kHz. speed: The speed of the model's spoken response. 1.0 is the default speed. 0.25 is the minimum speed. 1.5 is the maximum speed. This value can only be changed in between model turns, not while a response is in progress. temperature: Sampling temperature for the model, limited to [0.6, 1.2]. For audio models a temperature of 0.8 is highly recommended for best performance. tool_choice: How the model chooses tools. Options are `auto`, `none`, `required`, or specify a function. tools: Tools (functions) available to the model. tracing: Configuration options for tracing. Set to null to disable tracing. Once tracing is enabled for a session, the configuration cannot be modified. `auto` will create a trace for the session with default values for the workflow name, group id, and metadata. turn_detection: Configuration for turn detection, ether Server VAD or Semantic VAD. This can be set to `null` to turn off, in which case the client must manually trigger model response. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. Semantic VAD is more advanced and uses a turn detection model (in conjunction with VAD) to semantically estimate whether the user has finished speaking, then dynamically sets a timeout based on this probability. For example, if user audio trails off with "uhhm", the model will score a low probability of turn end and wait longer for the user to continue speaking. This can be useful for more natural conversations, but may have a higher latency. voice: The voice the model uses to respond. Voice cannot be changed during the session once the model has responded with audio at least once. Current voice options are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, and `verse`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._post( "/realtime/sessions", body=await async_maybe_transform( { "client_secret": client_secret, "input_audio_format": input_audio_format, "input_audio_noise_reduction": input_audio_noise_reduction, "input_audio_transcription": input_audio_transcription, "instructions": instructions, "max_response_output_tokens": max_response_output_tokens, "modalities": modalities, "model": model, "output_audio_format": output_audio_format, "speed": speed, "temperature": temperature, "tool_choice": tool_choice, "tools": tools, "tracing": tracing, "turn_detection": turn_detection, "voice": voice, }, session_create_params.SessionCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=SessionCreateResponse, ) class SessionsWithRawResponse: def __init__(self, sessions: Sessions) -> None: self._sessions = sessions self.create = _legacy_response.to_raw_response_wrapper( sessions.create, ) class AsyncSessionsWithRawResponse: def __init__(self, sessions: AsyncSessions) -> None: self._sessions = sessions self.create = _legacy_response.async_to_raw_response_wrapper( sessions.create, ) class SessionsWithStreamingResponse: def __init__(self, sessions: Sessions) -> None: self._sessions = sessions self.create = to_streamed_response_wrapper( sessions.create, ) class AsyncSessionsWithStreamingResponse: def __init__(self, sessions: AsyncSessions) -> None: self._sessions = sessions self.create = async_to_streamed_response_wrapper( sessions.create, ) ================================================ FILE: src/openai/resources/beta/realtime/transcription_sessions.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List from typing_extensions import Literal import httpx from .... import _legacy_response from ...._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ...._utils import maybe_transform, async_maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ...._base_client import make_request_options from ....types.beta.realtime import transcription_session_create_params from ....types.beta.realtime.transcription_session import TranscriptionSession __all__ = ["TranscriptionSessions", "AsyncTranscriptionSessions"] class TranscriptionSessions(SyncAPIResource): @cached_property def with_raw_response(self) -> TranscriptionSessionsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return TranscriptionSessionsWithRawResponse(self) @cached_property def with_streaming_response(self) -> TranscriptionSessionsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return TranscriptionSessionsWithStreamingResponse(self) def create( self, *, client_secret: transcription_session_create_params.ClientSecret | NotGiven = NOT_GIVEN, include: List[str] | NotGiven = NOT_GIVEN, input_audio_format: Literal["pcm16", "g711_ulaw", "g711_alaw"] | NotGiven = NOT_GIVEN, input_audio_noise_reduction: transcription_session_create_params.InputAudioNoiseReduction | NotGiven = NOT_GIVEN, input_audio_transcription: transcription_session_create_params.InputAudioTranscription | NotGiven = NOT_GIVEN, modalities: List[Literal["text", "audio"]] | NotGiven = NOT_GIVEN, turn_detection: transcription_session_create_params.TurnDetection | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> TranscriptionSession: """ Create an ephemeral API token for use in client-side applications with the Realtime API specifically for realtime transcriptions. Can be configured with the same session parameters as the `transcription_session.update` client event. It responds with a session object, plus a `client_secret` key which contains a usable ephemeral API token that can be used to authenticate browser clients for the Realtime API. Args: client_secret: Configuration options for the generated client secret. include: The set of items to include in the transcription. Current available items are: - `item.input_audio_transcription.logprobs` input_audio_format: The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`. For `pcm16`, input audio must be 16-bit PCM at a 24kHz sample rate, single channel (mono), and little-endian byte order. input_audio_noise_reduction: Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. input_audio_transcription: Configuration for input audio transcription. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service. modalities: The set of modalities the model can respond with. To disable audio, set this to ["text"]. turn_detection: Configuration for turn detection, ether Server VAD or Semantic VAD. This can be set to `null` to turn off, in which case the client must manually trigger model response. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. Semantic VAD is more advanced and uses a turn detection model (in conjunction with VAD) to semantically estimate whether the user has finished speaking, then dynamically sets a timeout based on this probability. For example, if user audio trails off with "uhhm", the model will score a low probability of turn end and wait longer for the user to continue speaking. This can be useful for more natural conversations, but may have a higher latency. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._post( "/realtime/transcription_sessions", body=maybe_transform( { "client_secret": client_secret, "include": include, "input_audio_format": input_audio_format, "input_audio_noise_reduction": input_audio_noise_reduction, "input_audio_transcription": input_audio_transcription, "modalities": modalities, "turn_detection": turn_detection, }, transcription_session_create_params.TranscriptionSessionCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=TranscriptionSession, ) class AsyncTranscriptionSessions(AsyncAPIResource): @cached_property def with_raw_response(self) -> AsyncTranscriptionSessionsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncTranscriptionSessionsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncTranscriptionSessionsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncTranscriptionSessionsWithStreamingResponse(self) async def create( self, *, client_secret: transcription_session_create_params.ClientSecret | NotGiven = NOT_GIVEN, include: List[str] | NotGiven = NOT_GIVEN, input_audio_format: Literal["pcm16", "g711_ulaw", "g711_alaw"] | NotGiven = NOT_GIVEN, input_audio_noise_reduction: transcription_session_create_params.InputAudioNoiseReduction | NotGiven = NOT_GIVEN, input_audio_transcription: transcription_session_create_params.InputAudioTranscription | NotGiven = NOT_GIVEN, modalities: List[Literal["text", "audio"]] | NotGiven = NOT_GIVEN, turn_detection: transcription_session_create_params.TurnDetection | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> TranscriptionSession: """ Create an ephemeral API token for use in client-side applications with the Realtime API specifically for realtime transcriptions. Can be configured with the same session parameters as the `transcription_session.update` client event. It responds with a session object, plus a `client_secret` key which contains a usable ephemeral API token that can be used to authenticate browser clients for the Realtime API. Args: client_secret: Configuration options for the generated client secret. include: The set of items to include in the transcription. Current available items are: - `item.input_audio_transcription.logprobs` input_audio_format: The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`. For `pcm16`, input audio must be 16-bit PCM at a 24kHz sample rate, single channel (mono), and little-endian byte order. input_audio_noise_reduction: Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. input_audio_transcription: Configuration for input audio transcription. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service. modalities: The set of modalities the model can respond with. To disable audio, set this to ["text"]. turn_detection: Configuration for turn detection, ether Server VAD or Semantic VAD. This can be set to `null` to turn off, in which case the client must manually trigger model response. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. Semantic VAD is more advanced and uses a turn detection model (in conjunction with VAD) to semantically estimate whether the user has finished speaking, then dynamically sets a timeout based on this probability. For example, if user audio trails off with "uhhm", the model will score a low probability of turn end and wait longer for the user to continue speaking. This can be useful for more natural conversations, but may have a higher latency. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._post( "/realtime/transcription_sessions", body=await async_maybe_transform( { "client_secret": client_secret, "include": include, "input_audio_format": input_audio_format, "input_audio_noise_reduction": input_audio_noise_reduction, "input_audio_transcription": input_audio_transcription, "modalities": modalities, "turn_detection": turn_detection, }, transcription_session_create_params.TranscriptionSessionCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=TranscriptionSession, ) class TranscriptionSessionsWithRawResponse: def __init__(self, transcription_sessions: TranscriptionSessions) -> None: self._transcription_sessions = transcription_sessions self.create = _legacy_response.to_raw_response_wrapper( transcription_sessions.create, ) class AsyncTranscriptionSessionsWithRawResponse: def __init__(self, transcription_sessions: AsyncTranscriptionSessions) -> None: self._transcription_sessions = transcription_sessions self.create = _legacy_response.async_to_raw_response_wrapper( transcription_sessions.create, ) class TranscriptionSessionsWithStreamingResponse: def __init__(self, transcription_sessions: TranscriptionSessions) -> None: self._transcription_sessions = transcription_sessions self.create = to_streamed_response_wrapper( transcription_sessions.create, ) class AsyncTranscriptionSessionsWithStreamingResponse: def __init__(self, transcription_sessions: AsyncTranscriptionSessions) -> None: self._transcription_sessions = transcription_sessions self.create = async_to_streamed_response_wrapper( transcription_sessions.create, ) ================================================ FILE: src/openai/resources/beta/threads/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .runs import ( Runs, AsyncRuns, RunsWithRawResponse, AsyncRunsWithRawResponse, RunsWithStreamingResponse, AsyncRunsWithStreamingResponse, ) from .threads import ( Threads, AsyncThreads, ThreadsWithRawResponse, AsyncThreadsWithRawResponse, ThreadsWithStreamingResponse, AsyncThreadsWithStreamingResponse, ) from .messages import ( Messages, AsyncMessages, MessagesWithRawResponse, AsyncMessagesWithRawResponse, MessagesWithStreamingResponse, AsyncMessagesWithStreamingResponse, ) __all__ = [ "Runs", "AsyncRuns", "RunsWithRawResponse", "AsyncRunsWithRawResponse", "RunsWithStreamingResponse", "AsyncRunsWithStreamingResponse", "Messages", "AsyncMessages", "MessagesWithRawResponse", "AsyncMessagesWithRawResponse", "MessagesWithStreamingResponse", "AsyncMessagesWithStreamingResponse", "Threads", "AsyncThreads", "ThreadsWithRawResponse", "AsyncThreadsWithRawResponse", "ThreadsWithStreamingResponse", "AsyncThreadsWithStreamingResponse", ] ================================================ FILE: src/openai/resources/beta/threads/messages.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import typing_extensions from typing import Union, Iterable, Optional from typing_extensions import Literal import httpx from .... import _legacy_response from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ...._utils import maybe_transform, async_maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ....pagination import SyncCursorPage, AsyncCursorPage from ...._base_client import ( AsyncPaginator, make_request_options, ) from ....types.beta.threads import message_list_params, message_create_params, message_update_params from ....types.beta.threads.message import Message from ....types.shared_params.metadata import Metadata from ....types.beta.threads.message_deleted import MessageDeleted from ....types.beta.threads.message_content_part_param import MessageContentPartParam __all__ = ["Messages", "AsyncMessages"] class Messages(SyncAPIResource): """Build Assistants that can call models and use tools.""" @cached_property def with_raw_response(self) -> MessagesWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return MessagesWithRawResponse(self) @cached_property def with_streaming_response(self) -> MessagesWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return MessagesWithStreamingResponse(self) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def create( self, thread_id: str, *, content: Union[str, Iterable[MessageContentPartParam]], role: Literal["user", "assistant"], attachments: Optional[Iterable[message_create_params.Attachment]] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Message: """ Create a message. Args: content: The text contents of the message. role: The role of the entity that is creating the message. Allowed values include: - `user`: Indicates the message is sent by an actual user and should be used in most cases to represent user-generated messages. - `assistant`: Indicates the message is generated by the assistant. Use this value to insert messages from the assistant into the conversation. attachments: A list of files attached to the message, and the tools they should be added to. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._post( f"/threads/{thread_id}/messages", body=maybe_transform( { "content": content, "role": role, "attachments": attachments, "metadata": metadata, }, message_create_params.MessageCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Message, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def retrieve( self, message_id: str, *, thread_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Message: """ Retrieve a message. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") if not message_id: raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get( f"/threads/{thread_id}/messages/{message_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Message, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def update( self, message_id: str, *, thread_id: str, metadata: Optional[Metadata] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Message: """ Modifies a message. Args: metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") if not message_id: raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._post( f"/threads/{thread_id}/messages/{message_id}", body=maybe_transform({"metadata": metadata}, message_update_params.MessageUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Message, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def list( self, thread_id: str, *, after: str | Omit = omit, before: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, run_id: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[Message]: """ Returns a list of messages for a given thread. Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. before: A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. run_id: Filter messages by the run ID that generated them. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get_api_list( f"/threads/{thread_id}/messages", page=SyncCursorPage[Message], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "limit": limit, "order": order, "run_id": run_id, }, message_list_params.MessageListParams, ), ), model=Message, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def delete( self, message_id: str, *, thread_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MessageDeleted: """ Deletes a message. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") if not message_id: raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._delete( f"/threads/{thread_id}/messages/{message_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=MessageDeleted, ) class AsyncMessages(AsyncAPIResource): """Build Assistants that can call models and use tools.""" @cached_property def with_raw_response(self) -> AsyncMessagesWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncMessagesWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncMessagesWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncMessagesWithStreamingResponse(self) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def create( self, thread_id: str, *, content: Union[str, Iterable[MessageContentPartParam]], role: Literal["user", "assistant"], attachments: Optional[Iterable[message_create_params.Attachment]] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Message: """ Create a message. Args: content: The text contents of the message. role: The role of the entity that is creating the message. Allowed values include: - `user`: Indicates the message is sent by an actual user and should be used in most cases to represent user-generated messages. - `assistant`: Indicates the message is generated by the assistant. Use this value to insert messages from the assistant into the conversation. attachments: A list of files attached to the message, and the tools they should be added to. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._post( f"/threads/{thread_id}/messages", body=await async_maybe_transform( { "content": content, "role": role, "attachments": attachments, "metadata": metadata, }, message_create_params.MessageCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Message, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def retrieve( self, message_id: str, *, thread_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Message: """ Retrieve a message. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") if not message_id: raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._get( f"/threads/{thread_id}/messages/{message_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Message, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def update( self, message_id: str, *, thread_id: str, metadata: Optional[Metadata] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Message: """ Modifies a message. Args: metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") if not message_id: raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._post( f"/threads/{thread_id}/messages/{message_id}", body=await async_maybe_transform({"metadata": metadata}, message_update_params.MessageUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Message, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def list( self, thread_id: str, *, after: str | Omit = omit, before: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, run_id: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[Message, AsyncCursorPage[Message]]: """ Returns a list of messages for a given thread. Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. before: A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. run_id: Filter messages by the run ID that generated them. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get_api_list( f"/threads/{thread_id}/messages", page=AsyncCursorPage[Message], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "limit": limit, "order": order, "run_id": run_id, }, message_list_params.MessageListParams, ), ), model=Message, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def delete( self, message_id: str, *, thread_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MessageDeleted: """ Deletes a message. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") if not message_id: raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._delete( f"/threads/{thread_id}/messages/{message_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=MessageDeleted, ) class MessagesWithRawResponse: def __init__(self, messages: Messages) -> None: self._messages = messages self.create = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( messages.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( messages.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( messages.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( messages.list, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( messages.delete, # pyright: ignore[reportDeprecated], ) ) class AsyncMessagesWithRawResponse: def __init__(self, messages: AsyncMessages) -> None: self._messages = messages self.create = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( messages.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( messages.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( messages.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( messages.list, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( messages.delete, # pyright: ignore[reportDeprecated], ) ) class MessagesWithStreamingResponse: def __init__(self, messages: Messages) -> None: self._messages = messages self.create = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( messages.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( messages.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( messages.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( messages.list, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( messages.delete, # pyright: ignore[reportDeprecated], ) ) class AsyncMessagesWithStreamingResponse: def __init__(self, messages: AsyncMessages) -> None: self._messages = messages self.create = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( messages.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( messages.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( messages.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( messages.list, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( messages.delete, # pyright: ignore[reportDeprecated], ) ) ================================================ FILE: src/openai/resources/beta/threads/runs/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .runs import ( Runs, AsyncRuns, RunsWithRawResponse, AsyncRunsWithRawResponse, RunsWithStreamingResponse, AsyncRunsWithStreamingResponse, ) from .steps import ( Steps, AsyncSteps, StepsWithRawResponse, AsyncStepsWithRawResponse, StepsWithStreamingResponse, AsyncStepsWithStreamingResponse, ) __all__ = [ "Steps", "AsyncSteps", "StepsWithRawResponse", "AsyncStepsWithRawResponse", "StepsWithStreamingResponse", "AsyncStepsWithStreamingResponse", "Runs", "AsyncRuns", "RunsWithRawResponse", "AsyncRunsWithRawResponse", "RunsWithStreamingResponse", "AsyncRunsWithStreamingResponse", ] ================================================ FILE: src/openai/resources/beta/threads/runs/runs.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import typing_extensions from typing import List, Union, Iterable, Optional from functools import partial from typing_extensions import Literal, overload import httpx from ..... import _legacy_response from .steps import ( Steps, AsyncSteps, StepsWithRawResponse, AsyncStepsWithRawResponse, StepsWithStreamingResponse, AsyncStepsWithStreamingResponse, ) from ....._types import NOT_GIVEN, Body, Omit, Query, Headers, NotGiven, omit, not_given from ....._utils import ( is_given, required_args, maybe_transform, async_maybe_transform, ) from ....._compat import cached_property from ....._resource import SyncAPIResource, AsyncAPIResource from ....._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ....._streaming import Stream, AsyncStream from .....pagination import SyncCursorPage, AsyncCursorPage from ....._base_client import AsyncPaginator, make_request_options from .....lib.streaming import ( AssistantEventHandler, AssistantEventHandlerT, AssistantStreamManager, AsyncAssistantEventHandler, AsyncAssistantEventHandlerT, AsyncAssistantStreamManager, ) from .....types.beta.threads import ( run_list_params, run_create_params, run_update_params, run_submit_tool_outputs_params, ) from .....types.beta.threads.run import Run from .....types.shared.chat_model import ChatModel from .....types.shared_params.metadata import Metadata from .....types.shared.reasoning_effort import ReasoningEffort from .....types.beta.assistant_tool_param import AssistantToolParam from .....types.beta.assistant_stream_event import AssistantStreamEvent from .....types.beta.threads.runs.run_step_include import RunStepInclude from .....types.beta.assistant_tool_choice_option_param import AssistantToolChoiceOptionParam from .....types.beta.assistant_response_format_option_param import AssistantResponseFormatOptionParam __all__ = ["Runs", "AsyncRuns"] class Runs(SyncAPIResource): """Build Assistants that can call models and use tools.""" @cached_property def steps(self) -> Steps: """Build Assistants that can call models and use tools.""" return Steps(self._client) @cached_property def with_raw_response(self) -> RunsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return RunsWithRawResponse(self) @cached_property def with_streaming_response(self) -> RunsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return RunsWithStreamingResponse(self) @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def create( self, thread_id: str, *, assistant_id: str, include: List[RunStepInclude] | Omit = omit, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, stream: Optional[Literal[False]] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run: """ Create a run. Args: assistant_id: The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to use to execute this run. include: A list of additional fields to include in the response. Currently the only supported value is `step_details.tool_calls[*].file_search.results[*].content` to fetch the file search result content. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) for more information. additional_instructions: Appends additional instructions at the end of the instructions for the run. This is useful for modifying the behavior on a per-run basis without overriding other instructions. additional_messages: Adds additional messages to the thread before creating the run. instructions: Overrides the [instructions](https://platform.openai.com/docs/api-reference/assistants/createAssistant) of the assistant. This is useful for modifying the behavior on a per-run basis. max_completion_tokens: The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. max_prompt_tokens: The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used. parallel_tool_calls: Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. reasoning_effort: Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. response_format: Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. stream: If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tools and instead generates a message. `auto` is the default value and means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools before responding to the user. Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. tools: Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. truncation_strategy: Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def create( self, thread_id: str, *, assistant_id: str, stream: Literal[True], include: List[RunStepInclude] | Omit = omit, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Stream[AssistantStreamEvent]: """ Create a run. Args: assistant_id: The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to use to execute this run. stream: If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. include: A list of additional fields to include in the response. Currently the only supported value is `step_details.tool_calls[*].file_search.results[*].content` to fetch the file search result content. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) for more information. additional_instructions: Appends additional instructions at the end of the instructions for the run. This is useful for modifying the behavior on a per-run basis without overriding other instructions. additional_messages: Adds additional messages to the thread before creating the run. instructions: Overrides the [instructions](https://platform.openai.com/docs/api-reference/assistants/createAssistant) of the assistant. This is useful for modifying the behavior on a per-run basis. max_completion_tokens: The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. max_prompt_tokens: The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used. parallel_tool_calls: Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. reasoning_effort: Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. response_format: Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tools and instead generates a message. `auto` is the default value and means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools before responding to the user. Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. tools: Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. truncation_strategy: Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def create( self, thread_id: str, *, assistant_id: str, stream: bool, include: List[RunStepInclude] | Omit = omit, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run | Stream[AssistantStreamEvent]: """ Create a run. Args: assistant_id: The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to use to execute this run. stream: If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. include: A list of additional fields to include in the response. Currently the only supported value is `step_details.tool_calls[*].file_search.results[*].content` to fetch the file search result content. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) for more information. additional_instructions: Appends additional instructions at the end of the instructions for the run. This is useful for modifying the behavior on a per-run basis without overriding other instructions. additional_messages: Adds additional messages to the thread before creating the run. instructions: Overrides the [instructions](https://platform.openai.com/docs/api-reference/assistants/createAssistant) of the assistant. This is useful for modifying the behavior on a per-run basis. max_completion_tokens: The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. max_prompt_tokens: The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used. parallel_tool_calls: Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. reasoning_effort: Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. response_format: Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tools and instead generates a message. `auto` is the default value and means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools before responding to the user. Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. tools: Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. truncation_strategy: Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") @required_args(["assistant_id"], ["assistant_id", "stream"]) def create( self, thread_id: str, *, assistant_id: str, include: List[RunStepInclude] | Omit = omit, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, stream: Optional[Literal[False]] | Literal[True] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run | Stream[AssistantStreamEvent]: if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._post( f"/threads/{thread_id}/runs", body=maybe_transform( { "assistant_id": assistant_id, "additional_instructions": additional_instructions, "additional_messages": additional_messages, "instructions": instructions, "max_completion_tokens": max_completion_tokens, "max_prompt_tokens": max_prompt_tokens, "metadata": metadata, "model": model, "parallel_tool_calls": parallel_tool_calls, "reasoning_effort": reasoning_effort, "response_format": response_format, "stream": stream, "temperature": temperature, "tool_choice": tool_choice, "tools": tools, "top_p": top_p, "truncation_strategy": truncation_strategy, }, run_create_params.RunCreateParamsStreaming if stream else run_create_params.RunCreateParamsNonStreaming, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform({"include": include}, run_create_params.RunCreateParams), synthesize_event_and_data=True, ), cast_to=Run, stream=stream or False, stream_cls=Stream[AssistantStreamEvent], ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def retrieve( self, run_id: str, *, thread_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run: """ Retrieves a run. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get( f"/threads/{thread_id}/runs/{run_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Run, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def update( self, run_id: str, *, thread_id: str, metadata: Optional[Metadata] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run: """ Modifies a run. Args: metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._post( f"/threads/{thread_id}/runs/{run_id}", body=maybe_transform({"metadata": metadata}, run_update_params.RunUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Run, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def list( self, thread_id: str, *, after: str | Omit = omit, before: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[Run]: """ Returns a list of runs belonging to a thread. Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. before: A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get_api_list( f"/threads/{thread_id}/runs", page=SyncCursorPage[Run], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "limit": limit, "order": order, }, run_list_params.RunListParams, ), ), model=Run, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def cancel( self, run_id: str, *, thread_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run: """ Cancels a run that is `in_progress`. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._post( f"/threads/{thread_id}/runs/{run_id}/cancel", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Run, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def create_and_poll( self, *, assistant_id: str, include: List[RunStepInclude] | Omit = omit, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, poll_interval_ms: int | Omit = omit, thread_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Run: """ A helper to create a run an poll for a terminal state. More information on Run lifecycles can be found here: https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps """ run = self.create( # pyright: ignore[reportDeprecated] thread_id=thread_id, assistant_id=assistant_id, include=include, additional_instructions=additional_instructions, additional_messages=additional_messages, instructions=instructions, max_completion_tokens=max_completion_tokens, max_prompt_tokens=max_prompt_tokens, metadata=metadata, model=model, response_format=response_format, temperature=temperature, tool_choice=tool_choice, parallel_tool_calls=parallel_tool_calls, reasoning_effort=reasoning_effort, # We assume we are not streaming when polling stream=False, tools=tools, truncation_strategy=truncation_strategy, top_p=top_p, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, ) return self.poll( # pyright: ignore[reportDeprecated] run.id, thread_id=thread_id, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, poll_interval_ms=poll_interval_ms, timeout=timeout, ) @overload @typing_extensions.deprecated("use `stream` instead") def create_and_stream( self, *, assistant_id: str, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, thread_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AssistantStreamManager[AssistantEventHandler]: """Create a Run stream""" ... @overload @typing_extensions.deprecated("use `stream` instead") def create_and_stream( self, *, assistant_id: str, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, thread_id: str, event_handler: AssistantEventHandlerT, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AssistantStreamManager[AssistantEventHandlerT]: """Create a Run stream""" ... @typing_extensions.deprecated("use `stream` instead") def create_and_stream( self, *, assistant_id: str, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, thread_id: str, event_handler: AssistantEventHandlerT | None = None, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AssistantStreamManager[AssistantEventHandler] | AssistantStreamManager[AssistantEventHandlerT]: """Create a Run stream""" if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = { "OpenAI-Beta": "assistants=v2", "X-Stainless-Stream-Helper": "threads.runs.create_and_stream", "X-Stainless-Custom-Event-Handler": "true" if event_handler else "false", **(extra_headers or {}), } make_request = partial( self._post, f"/threads/{thread_id}/runs", body=maybe_transform( { "assistant_id": assistant_id, "additional_instructions": additional_instructions, "additional_messages": additional_messages, "instructions": instructions, "max_completion_tokens": max_completion_tokens, "max_prompt_tokens": max_prompt_tokens, "metadata": metadata, "model": model, "response_format": response_format, "temperature": temperature, "tool_choice": tool_choice, "stream": True, "tools": tools, "truncation_strategy": truncation_strategy, "parallel_tool_calls": parallel_tool_calls, "reasoning_effort": reasoning_effort, "top_p": top_p, }, run_create_params.RunCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Run, stream=True, stream_cls=Stream[AssistantStreamEvent], ) return AssistantStreamManager(make_request, event_handler=event_handler or AssistantEventHandler()) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def poll( self, run_id: str, thread_id: str, extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, poll_interval_ms: int | Omit = omit, ) -> Run: """ A helper to poll a run status until it reaches a terminal state. More information on Run lifecycles can be found here: https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps """ extra_headers = {"X-Stainless-Poll-Helper": "true", **(extra_headers or {})} if is_given(poll_interval_ms): extra_headers["X-Stainless-Custom-Poll-Interval"] = str(poll_interval_ms) terminal_states = {"requires_action", "cancelled", "completed", "failed", "expired", "incomplete"} while True: response = self.with_raw_response.retrieve( # pyright: ignore[reportDeprecated] thread_id=thread_id, run_id=run_id, extra_headers=extra_headers, extra_body=extra_body, extra_query=extra_query, timeout=timeout, ) run = response.parse() # Return if we reached a terminal state if run.status in terminal_states: return run if not is_given(poll_interval_ms): from_header = response.headers.get("openai-poll-after-ms") if from_header is not None: poll_interval_ms = int(from_header) else: poll_interval_ms = 1000 self._sleep(poll_interval_ms / 1000) @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def stream( self, *, assistant_id: str, include: List[RunStepInclude] | Omit = omit, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, thread_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AssistantStreamManager[AssistantEventHandler]: """Create a Run stream""" ... @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def stream( self, *, assistant_id: str, include: List[RunStepInclude] | Omit = omit, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, thread_id: str, event_handler: AssistantEventHandlerT, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AssistantStreamManager[AssistantEventHandlerT]: """Create a Run stream""" ... @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def stream( self, *, assistant_id: str, include: List[RunStepInclude] | Omit = omit, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, thread_id: str, event_handler: AssistantEventHandlerT | None = None, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AssistantStreamManager[AssistantEventHandler] | AssistantStreamManager[AssistantEventHandlerT]: """Create a Run stream""" if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = { "OpenAI-Beta": "assistants=v2", "X-Stainless-Stream-Helper": "threads.runs.create_and_stream", "X-Stainless-Custom-Event-Handler": "true" if event_handler else "false", **(extra_headers or {}), } make_request = partial( self._post, f"/threads/{thread_id}/runs", body=maybe_transform( { "assistant_id": assistant_id, "additional_instructions": additional_instructions, "additional_messages": additional_messages, "instructions": instructions, "max_completion_tokens": max_completion_tokens, "max_prompt_tokens": max_prompt_tokens, "metadata": metadata, "model": model, "response_format": response_format, "temperature": temperature, "tool_choice": tool_choice, "stream": True, "tools": tools, "parallel_tool_calls": parallel_tool_calls, "reasoning_effort": reasoning_effort, "truncation_strategy": truncation_strategy, "top_p": top_p, }, run_create_params.RunCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform({"include": include}, run_create_params.RunCreateParams), ), cast_to=Run, stream=True, stream_cls=Stream[AssistantStreamEvent], ) return AssistantStreamManager(make_request, event_handler=event_handler or AssistantEventHandler()) @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def submit_tool_outputs( self, run_id: str, *, thread_id: str, tool_outputs: Iterable[run_submit_tool_outputs_params.ToolOutput], stream: Optional[Literal[False]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run: """ When a run has the `status: "requires_action"` and `required_action.type` is `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once they're all completed. All outputs must be submitted in a single request. Args: tool_outputs: A list of tools for which the outputs are being submitted. stream: If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def submit_tool_outputs( self, run_id: str, *, thread_id: str, stream: Literal[True], tool_outputs: Iterable[run_submit_tool_outputs_params.ToolOutput], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Stream[AssistantStreamEvent]: """ When a run has the `status: "requires_action"` and `required_action.type` is `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once they're all completed. All outputs must be submitted in a single request. Args: stream: If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. tool_outputs: A list of tools for which the outputs are being submitted. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def submit_tool_outputs( self, run_id: str, *, thread_id: str, stream: bool, tool_outputs: Iterable[run_submit_tool_outputs_params.ToolOutput], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run | Stream[AssistantStreamEvent]: """ When a run has the `status: "requires_action"` and `required_action.type` is `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once they're all completed. All outputs must be submitted in a single request. Args: stream: If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. tool_outputs: A list of tools for which the outputs are being submitted. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") @required_args(["thread_id", "tool_outputs"], ["thread_id", "stream", "tool_outputs"]) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def submit_tool_outputs( self, run_id: str, *, thread_id: str, tool_outputs: Iterable[run_submit_tool_outputs_params.ToolOutput], stream: Optional[Literal[False]] | Literal[True] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run | Stream[AssistantStreamEvent]: if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._post( f"/threads/{thread_id}/runs/{run_id}/submit_tool_outputs", body=maybe_transform( { "tool_outputs": tool_outputs, "stream": stream, }, run_submit_tool_outputs_params.RunSubmitToolOutputsParamsStreaming if stream else run_submit_tool_outputs_params.RunSubmitToolOutputsParamsNonStreaming, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, synthesize_event_and_data=True, ), cast_to=Run, stream=stream or False, stream_cls=Stream[AssistantStreamEvent], ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def submit_tool_outputs_and_poll( self, *, tool_outputs: Iterable[run_submit_tool_outputs_params.ToolOutput], run_id: str, thread_id: str, poll_interval_ms: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Run: """ A helper to submit a tool output to a run and poll for a terminal run state. More information on Run lifecycles can be found here: https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps """ run = self.submit_tool_outputs( # pyright: ignore[reportDeprecated] run_id=run_id, thread_id=thread_id, tool_outputs=tool_outputs, stream=False, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, ) return self.poll( # pyright: ignore[reportDeprecated] run_id=run.id, thread_id=thread_id, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, poll_interval_ms=poll_interval_ms, ) @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def submit_tool_outputs_stream( self, *, tool_outputs: Iterable[run_submit_tool_outputs_params.ToolOutput], run_id: str, thread_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AssistantStreamManager[AssistantEventHandler]: """ Submit the tool outputs from a previous run and stream the run to a terminal state. More information on Run lifecycles can be found here: https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps """ ... @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def submit_tool_outputs_stream( self, *, tool_outputs: Iterable[run_submit_tool_outputs_params.ToolOutput], run_id: str, thread_id: str, event_handler: AssistantEventHandlerT, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AssistantStreamManager[AssistantEventHandlerT]: """ Submit the tool outputs from a previous run and stream the run to a terminal state. More information on Run lifecycles can be found here: https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps """ ... @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def submit_tool_outputs_stream( self, *, tool_outputs: Iterable[run_submit_tool_outputs_params.ToolOutput], run_id: str, thread_id: str, event_handler: AssistantEventHandlerT | None = None, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AssistantStreamManager[AssistantEventHandler] | AssistantStreamManager[AssistantEventHandlerT]: """ Submit the tool outputs from a previous run and stream the run to a terminal state. More information on Run lifecycles can be found here: https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps """ if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = { "OpenAI-Beta": "assistants=v2", "X-Stainless-Stream-Helper": "threads.runs.submit_tool_outputs_stream", "X-Stainless-Custom-Event-Handler": "true" if event_handler else "false", **(extra_headers or {}), } request = partial( self._post, f"/threads/{thread_id}/runs/{run_id}/submit_tool_outputs", body=maybe_transform( { "tool_outputs": tool_outputs, "stream": True, }, run_submit_tool_outputs_params.RunSubmitToolOutputsParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Run, stream=True, stream_cls=Stream[AssistantStreamEvent], ) return AssistantStreamManager(request, event_handler=event_handler or AssistantEventHandler()) class AsyncRuns(AsyncAPIResource): """Build Assistants that can call models and use tools.""" @cached_property def steps(self) -> AsyncSteps: """Build Assistants that can call models and use tools.""" return AsyncSteps(self._client) @cached_property def with_raw_response(self) -> AsyncRunsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncRunsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncRunsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncRunsWithStreamingResponse(self) @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def create( self, thread_id: str, *, assistant_id: str, include: List[RunStepInclude] | Omit = omit, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, stream: Optional[Literal[False]] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run: """ Create a run. Args: assistant_id: The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to use to execute this run. include: A list of additional fields to include in the response. Currently the only supported value is `step_details.tool_calls[*].file_search.results[*].content` to fetch the file search result content. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) for more information. additional_instructions: Appends additional instructions at the end of the instructions for the run. This is useful for modifying the behavior on a per-run basis without overriding other instructions. additional_messages: Adds additional messages to the thread before creating the run. instructions: Overrides the [instructions](https://platform.openai.com/docs/api-reference/assistants/createAssistant) of the assistant. This is useful for modifying the behavior on a per-run basis. max_completion_tokens: The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. max_prompt_tokens: The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used. parallel_tool_calls: Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. reasoning_effort: Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. response_format: Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. stream: If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tools and instead generates a message. `auto` is the default value and means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools before responding to the user. Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. tools: Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. truncation_strategy: Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def create( self, thread_id: str, *, assistant_id: str, stream: Literal[True], include: List[RunStepInclude] | Omit = omit, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncStream[AssistantStreamEvent]: """ Create a run. Args: assistant_id: The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to use to execute this run. stream: If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. include: A list of additional fields to include in the response. Currently the only supported value is `step_details.tool_calls[*].file_search.results[*].content` to fetch the file search result content. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) for more information. additional_instructions: Appends additional instructions at the end of the instructions for the run. This is useful for modifying the behavior on a per-run basis without overriding other instructions. additional_messages: Adds additional messages to the thread before creating the run. instructions: Overrides the [instructions](https://platform.openai.com/docs/api-reference/assistants/createAssistant) of the assistant. This is useful for modifying the behavior on a per-run basis. max_completion_tokens: The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. max_prompt_tokens: The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used. parallel_tool_calls: Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. reasoning_effort: Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. response_format: Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tools and instead generates a message. `auto` is the default value and means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools before responding to the user. Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. tools: Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. truncation_strategy: Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def create( self, thread_id: str, *, assistant_id: str, stream: bool, include: List[RunStepInclude] | Omit = omit, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run | AsyncStream[AssistantStreamEvent]: """ Create a run. Args: assistant_id: The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to use to execute this run. stream: If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. include: A list of additional fields to include in the response. Currently the only supported value is `step_details.tool_calls[*].file_search.results[*].content` to fetch the file search result content. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) for more information. additional_instructions: Appends additional instructions at the end of the instructions for the run. This is useful for modifying the behavior on a per-run basis without overriding other instructions. additional_messages: Adds additional messages to the thread before creating the run. instructions: Overrides the [instructions](https://platform.openai.com/docs/api-reference/assistants/createAssistant) of the assistant. This is useful for modifying the behavior on a per-run basis. max_completion_tokens: The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. max_prompt_tokens: The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used. parallel_tool_calls: Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. reasoning_effort: Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. response_format: Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tools and instead generates a message. `auto` is the default value and means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools before responding to the user. Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. tools: Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. truncation_strategy: Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") @required_args(["assistant_id"], ["assistant_id", "stream"]) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def create( self, thread_id: str, *, assistant_id: str, include: List[RunStepInclude] | Omit = omit, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, stream: Optional[Literal[False]] | Literal[True] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run | AsyncStream[AssistantStreamEvent]: if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._post( f"/threads/{thread_id}/runs", body=await async_maybe_transform( { "assistant_id": assistant_id, "additional_instructions": additional_instructions, "additional_messages": additional_messages, "instructions": instructions, "max_completion_tokens": max_completion_tokens, "max_prompt_tokens": max_prompt_tokens, "metadata": metadata, "model": model, "parallel_tool_calls": parallel_tool_calls, "reasoning_effort": reasoning_effort, "response_format": response_format, "stream": stream, "temperature": temperature, "tool_choice": tool_choice, "tools": tools, "top_p": top_p, "truncation_strategy": truncation_strategy, }, run_create_params.RunCreateParamsStreaming if stream else run_create_params.RunCreateParamsNonStreaming, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=await async_maybe_transform({"include": include}, run_create_params.RunCreateParams), synthesize_event_and_data=True, ), cast_to=Run, stream=stream or False, stream_cls=AsyncStream[AssistantStreamEvent], ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def retrieve( self, run_id: str, *, thread_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run: """ Retrieves a run. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._get( f"/threads/{thread_id}/runs/{run_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Run, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def update( self, run_id: str, *, thread_id: str, metadata: Optional[Metadata] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run: """ Modifies a run. Args: metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._post( f"/threads/{thread_id}/runs/{run_id}", body=await async_maybe_transform({"metadata": metadata}, run_update_params.RunUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Run, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def list( self, thread_id: str, *, after: str | Omit = omit, before: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[Run, AsyncCursorPage[Run]]: """ Returns a list of runs belonging to a thread. Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. before: A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get_api_list( f"/threads/{thread_id}/runs", page=AsyncCursorPage[Run], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "limit": limit, "order": order, }, run_list_params.RunListParams, ), ), model=Run, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def cancel( self, run_id: str, *, thread_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run: """ Cancels a run that is `in_progress`. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._post( f"/threads/{thread_id}/runs/{run_id}/cancel", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Run, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def create_and_poll( self, *, assistant_id: str, include: List[RunStepInclude] | Omit = omit, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, poll_interval_ms: int | Omit = omit, thread_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Run: """ A helper to create a run an poll for a terminal state. More information on Run lifecycles can be found here: https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps """ run = await self.create( # pyright: ignore[reportDeprecated] thread_id=thread_id, assistant_id=assistant_id, include=include, additional_instructions=additional_instructions, additional_messages=additional_messages, instructions=instructions, max_completion_tokens=max_completion_tokens, max_prompt_tokens=max_prompt_tokens, metadata=metadata, model=model, response_format=response_format, temperature=temperature, tool_choice=tool_choice, parallel_tool_calls=parallel_tool_calls, reasoning_effort=reasoning_effort, # We assume we are not streaming when polling stream=False, tools=tools, truncation_strategy=truncation_strategy, top_p=top_p, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, ) return await self.poll( # pyright: ignore[reportDeprecated] run.id, thread_id=thread_id, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, poll_interval_ms=poll_interval_ms, timeout=timeout, ) @overload @typing_extensions.deprecated("use `stream` instead") def create_and_stream( self, *, assistant_id: str, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, thread_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncAssistantStreamManager[AsyncAssistantEventHandler]: """Create a Run stream""" ... @overload @typing_extensions.deprecated("use `stream` instead") def create_and_stream( self, *, assistant_id: str, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, thread_id: str, event_handler: AsyncAssistantEventHandlerT, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncAssistantStreamManager[AsyncAssistantEventHandlerT]: """Create a Run stream""" ... @typing_extensions.deprecated("use `stream` instead") def create_and_stream( self, *, assistant_id: str, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, thread_id: str, event_handler: AsyncAssistantEventHandlerT | None = None, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> ( AsyncAssistantStreamManager[AsyncAssistantEventHandler] | AsyncAssistantStreamManager[AsyncAssistantEventHandlerT] ): """Create a Run stream""" if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = { "OpenAI-Beta": "assistants=v2", "X-Stainless-Stream-Helper": "threads.runs.create_and_stream", "X-Stainless-Custom-Event-Handler": "true" if event_handler else "false", **(extra_headers or {}), } request = self._post( f"/threads/{thread_id}/runs", body=maybe_transform( { "assistant_id": assistant_id, "additional_instructions": additional_instructions, "additional_messages": additional_messages, "instructions": instructions, "max_completion_tokens": max_completion_tokens, "max_prompt_tokens": max_prompt_tokens, "metadata": metadata, "model": model, "response_format": response_format, "temperature": temperature, "tool_choice": tool_choice, "stream": True, "tools": tools, "truncation_strategy": truncation_strategy, "top_p": top_p, "parallel_tool_calls": parallel_tool_calls, }, run_create_params.RunCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Run, stream=True, stream_cls=AsyncStream[AssistantStreamEvent], ) return AsyncAssistantStreamManager(request, event_handler=event_handler or AsyncAssistantEventHandler()) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def poll( self, run_id: str, thread_id: str, extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, poll_interval_ms: int | Omit = omit, ) -> Run: """ A helper to poll a run status until it reaches a terminal state. More information on Run lifecycles can be found here: https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps """ extra_headers = {"X-Stainless-Poll-Helper": "true", **(extra_headers or {})} if is_given(poll_interval_ms): extra_headers["X-Stainless-Custom-Poll-Interval"] = str(poll_interval_ms) terminal_states = {"requires_action", "cancelled", "completed", "failed", "expired", "incomplete"} while True: response = await self.with_raw_response.retrieve( # pyright: ignore[reportDeprecated] thread_id=thread_id, run_id=run_id, extra_headers=extra_headers, extra_body=extra_body, extra_query=extra_query, timeout=timeout, ) run = response.parse() # Return if we reached a terminal state if run.status in terminal_states: return run if not is_given(poll_interval_ms): from_header = response.headers.get("openai-poll-after-ms") if from_header is not None: poll_interval_ms = int(from_header) else: poll_interval_ms = 1000 await self._sleep(poll_interval_ms / 1000) @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def stream( self, *, assistant_id: str, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, thread_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncAssistantStreamManager[AsyncAssistantEventHandler]: """Create a Run stream""" ... @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def stream( self, *, assistant_id: str, include: List[RunStepInclude] | Omit = omit, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, thread_id: str, event_handler: AsyncAssistantEventHandlerT, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncAssistantStreamManager[AsyncAssistantEventHandlerT]: """Create a Run stream""" ... @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def stream( self, *, assistant_id: str, include: List[RunStepInclude] | Omit = omit, additional_instructions: Optional[str] | Omit = omit, additional_messages: Optional[Iterable[run_create_params.AdditionalMessage]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[run_create_params.TruncationStrategy] | Omit = omit, thread_id: str, event_handler: AsyncAssistantEventHandlerT | None = None, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> ( AsyncAssistantStreamManager[AsyncAssistantEventHandler] | AsyncAssistantStreamManager[AsyncAssistantEventHandlerT] ): """Create a Run stream""" if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = { "OpenAI-Beta": "assistants=v2", "X-Stainless-Stream-Helper": "threads.runs.create_and_stream", "X-Stainless-Custom-Event-Handler": "true" if event_handler else "false", **(extra_headers or {}), } request = self._post( f"/threads/{thread_id}/runs", body=maybe_transform( { "assistant_id": assistant_id, "additional_instructions": additional_instructions, "additional_messages": additional_messages, "instructions": instructions, "max_completion_tokens": max_completion_tokens, "max_prompt_tokens": max_prompt_tokens, "metadata": metadata, "model": model, "response_format": response_format, "temperature": temperature, "tool_choice": tool_choice, "stream": True, "tools": tools, "parallel_tool_calls": parallel_tool_calls, "reasoning_effort": reasoning_effort, "truncation_strategy": truncation_strategy, "top_p": top_p, }, run_create_params.RunCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform({"include": include}, run_create_params.RunCreateParams), ), cast_to=Run, stream=True, stream_cls=AsyncStream[AssistantStreamEvent], ) return AsyncAssistantStreamManager(request, event_handler=event_handler or AsyncAssistantEventHandler()) @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def submit_tool_outputs( self, run_id: str, *, thread_id: str, tool_outputs: Iterable[run_submit_tool_outputs_params.ToolOutput], stream: Optional[Literal[False]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run: """ When a run has the `status: "requires_action"` and `required_action.type` is `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once they're all completed. All outputs must be submitted in a single request. Args: tool_outputs: A list of tools for which the outputs are being submitted. stream: If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def submit_tool_outputs( self, run_id: str, *, thread_id: str, stream: Literal[True], tool_outputs: Iterable[run_submit_tool_outputs_params.ToolOutput], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncStream[AssistantStreamEvent]: """ When a run has the `status: "requires_action"` and `required_action.type` is `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once they're all completed. All outputs must be submitted in a single request. Args: stream: If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. tool_outputs: A list of tools for which the outputs are being submitted. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def submit_tool_outputs( self, run_id: str, *, thread_id: str, stream: bool, tool_outputs: Iterable[run_submit_tool_outputs_params.ToolOutput], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run | AsyncStream[AssistantStreamEvent]: """ When a run has the `status: "requires_action"` and `required_action.type` is `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once they're all completed. All outputs must be submitted in a single request. Args: stream: If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. tool_outputs: A list of tools for which the outputs are being submitted. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") @required_args(["thread_id", "tool_outputs"], ["thread_id", "stream", "tool_outputs"]) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def submit_tool_outputs( self, run_id: str, *, thread_id: str, tool_outputs: Iterable[run_submit_tool_outputs_params.ToolOutput], stream: Optional[Literal[False]] | Literal[True] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run | AsyncStream[AssistantStreamEvent]: if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._post( f"/threads/{thread_id}/runs/{run_id}/submit_tool_outputs", body=await async_maybe_transform( { "tool_outputs": tool_outputs, "stream": stream, }, run_submit_tool_outputs_params.RunSubmitToolOutputsParamsStreaming if stream else run_submit_tool_outputs_params.RunSubmitToolOutputsParamsNonStreaming, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, synthesize_event_and_data=True, ), cast_to=Run, stream=stream or False, stream_cls=AsyncStream[AssistantStreamEvent], ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def submit_tool_outputs_and_poll( self, *, tool_outputs: Iterable[run_submit_tool_outputs_params.ToolOutput], run_id: str, thread_id: str, poll_interval_ms: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Run: """ A helper to submit a tool output to a run and poll for a terminal run state. More information on Run lifecycles can be found here: https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps """ run = await self.submit_tool_outputs( # pyright: ignore[reportDeprecated] run_id=run_id, thread_id=thread_id, tool_outputs=tool_outputs, stream=False, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, ) return await self.poll( # pyright: ignore[reportDeprecated] run_id=run.id, thread_id=thread_id, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, poll_interval_ms=poll_interval_ms, ) @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def submit_tool_outputs_stream( self, *, tool_outputs: Iterable[run_submit_tool_outputs_params.ToolOutput], run_id: str, thread_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncAssistantStreamManager[AsyncAssistantEventHandler]: """ Submit the tool outputs from a previous run and stream the run to a terminal state. More information on Run lifecycles can be found here: https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps """ ... @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def submit_tool_outputs_stream( self, *, tool_outputs: Iterable[run_submit_tool_outputs_params.ToolOutput], run_id: str, thread_id: str, event_handler: AsyncAssistantEventHandlerT, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncAssistantStreamManager[AsyncAssistantEventHandlerT]: """ Submit the tool outputs from a previous run and stream the run to a terminal state. More information on Run lifecycles can be found here: https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps """ ... @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def submit_tool_outputs_stream( self, *, tool_outputs: Iterable[run_submit_tool_outputs_params.ToolOutput], run_id: str, thread_id: str, event_handler: AsyncAssistantEventHandlerT | None = None, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> ( AsyncAssistantStreamManager[AsyncAssistantEventHandler] | AsyncAssistantStreamManager[AsyncAssistantEventHandlerT] ): """ Submit the tool outputs from a previous run and stream the run to a terminal state. More information on Run lifecycles can be found here: https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps """ if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = { "OpenAI-Beta": "assistants=v2", "X-Stainless-Stream-Helper": "threads.runs.submit_tool_outputs_stream", "X-Stainless-Custom-Event-Handler": "true" if event_handler else "false", **(extra_headers or {}), } request = self._post( f"/threads/{thread_id}/runs/{run_id}/submit_tool_outputs", body=maybe_transform( { "tool_outputs": tool_outputs, "stream": True, }, run_submit_tool_outputs_params.RunSubmitToolOutputsParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Run, stream=True, stream_cls=AsyncStream[AssistantStreamEvent], ) return AsyncAssistantStreamManager(request, event_handler=event_handler or AsyncAssistantEventHandler()) class RunsWithRawResponse: def __init__(self, runs: Runs) -> None: self._runs = runs self.create = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( runs.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( runs.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( runs.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( runs.list, # pyright: ignore[reportDeprecated], ) ) self.cancel = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( runs.cancel, # pyright: ignore[reportDeprecated], ) ) self.submit_tool_outputs = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( runs.submit_tool_outputs, # pyright: ignore[reportDeprecated], ) ) @cached_property def steps(self) -> StepsWithRawResponse: """Build Assistants that can call models and use tools.""" return StepsWithRawResponse(self._runs.steps) class AsyncRunsWithRawResponse: def __init__(self, runs: AsyncRuns) -> None: self._runs = runs self.create = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( runs.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( runs.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( runs.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( runs.list, # pyright: ignore[reportDeprecated], ) ) self.cancel = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( runs.cancel, # pyright: ignore[reportDeprecated], ) ) self.submit_tool_outputs = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( runs.submit_tool_outputs, # pyright: ignore[reportDeprecated], ) ) @cached_property def steps(self) -> AsyncStepsWithRawResponse: """Build Assistants that can call models and use tools.""" return AsyncStepsWithRawResponse(self._runs.steps) class RunsWithStreamingResponse: def __init__(self, runs: Runs) -> None: self._runs = runs self.create = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( runs.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( runs.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( runs.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( runs.list, # pyright: ignore[reportDeprecated], ) ) self.cancel = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( runs.cancel, # pyright: ignore[reportDeprecated], ) ) self.submit_tool_outputs = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( runs.submit_tool_outputs, # pyright: ignore[reportDeprecated], ) ) @cached_property def steps(self) -> StepsWithStreamingResponse: """Build Assistants that can call models and use tools.""" return StepsWithStreamingResponse(self._runs.steps) class AsyncRunsWithStreamingResponse: def __init__(self, runs: AsyncRuns) -> None: self._runs = runs self.create = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( runs.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( runs.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( runs.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( runs.list, # pyright: ignore[reportDeprecated], ) ) self.cancel = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( runs.cancel, # pyright: ignore[reportDeprecated], ) ) self.submit_tool_outputs = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( runs.submit_tool_outputs, # pyright: ignore[reportDeprecated], ) ) @cached_property def steps(self) -> AsyncStepsWithStreamingResponse: """Build Assistants that can call models and use tools.""" return AsyncStepsWithStreamingResponse(self._runs.steps) ================================================ FILE: src/openai/resources/beta/threads/runs/steps.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import typing_extensions from typing import List from typing_extensions import Literal import httpx from ..... import _legacy_response from ....._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ....._utils import maybe_transform, async_maybe_transform from ....._compat import cached_property from ....._resource import SyncAPIResource, AsyncAPIResource from ....._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from .....pagination import SyncCursorPage, AsyncCursorPage from ....._base_client import AsyncPaginator, make_request_options from .....types.beta.threads.runs import step_list_params, step_retrieve_params from .....types.beta.threads.runs.run_step import RunStep from .....types.beta.threads.runs.run_step_include import RunStepInclude __all__ = ["Steps", "AsyncSteps"] class Steps(SyncAPIResource): """Build Assistants that can call models and use tools.""" @cached_property def with_raw_response(self) -> StepsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return StepsWithRawResponse(self) @cached_property def with_streaming_response(self) -> StepsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return StepsWithStreamingResponse(self) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def retrieve( self, step_id: str, *, thread_id: str, run_id: str, include: List[RunStepInclude] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> RunStep: """ Retrieves a run step. Args: include: A list of additional fields to include in the response. Currently the only supported value is `step_details.tool_calls[*].file_search.results[*].content` to fetch the file search result content. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) for more information. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") if not step_id: raise ValueError(f"Expected a non-empty value for `step_id` but received {step_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get( f"/threads/{thread_id}/runs/{run_id}/steps/{step_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform({"include": include}, step_retrieve_params.StepRetrieveParams), ), cast_to=RunStep, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def list( self, run_id: str, *, thread_id: str, after: str | Omit = omit, before: str | Omit = omit, include: List[RunStepInclude] | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[RunStep]: """ Returns a list of run steps belonging to a run. Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. before: A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. include: A list of additional fields to include in the response. Currently the only supported value is `step_details.tool_calls[*].file_search.results[*].content` to fetch the file search result content. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) for more information. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get_api_list( f"/threads/{thread_id}/runs/{run_id}/steps", page=SyncCursorPage[RunStep], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "include": include, "limit": limit, "order": order, }, step_list_params.StepListParams, ), ), model=RunStep, ) class AsyncSteps(AsyncAPIResource): """Build Assistants that can call models and use tools.""" @cached_property def with_raw_response(self) -> AsyncStepsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncStepsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncStepsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncStepsWithStreamingResponse(self) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def retrieve( self, step_id: str, *, thread_id: str, run_id: str, include: List[RunStepInclude] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> RunStep: """ Retrieves a run step. Args: include: A list of additional fields to include in the response. Currently the only supported value is `step_details.tool_calls[*].file_search.results[*].content` to fetch the file search result content. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) for more information. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") if not step_id: raise ValueError(f"Expected a non-empty value for `step_id` but received {step_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._get( f"/threads/{thread_id}/runs/{run_id}/steps/{step_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=await async_maybe_transform({"include": include}, step_retrieve_params.StepRetrieveParams), ), cast_to=RunStep, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def list( self, run_id: str, *, thread_id: str, after: str | Omit = omit, before: str | Omit = omit, include: List[RunStepInclude] | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[RunStep, AsyncCursorPage[RunStep]]: """ Returns a list of run steps belonging to a run. Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. before: A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. include: A list of additional fields to include in the response. Currently the only supported value is `step_details.tool_calls[*].file_search.results[*].content` to fetch the file search result content. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) for more information. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get_api_list( f"/threads/{thread_id}/runs/{run_id}/steps", page=AsyncCursorPage[RunStep], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "include": include, "limit": limit, "order": order, }, step_list_params.StepListParams, ), ), model=RunStep, ) class StepsWithRawResponse: def __init__(self, steps: Steps) -> None: self._steps = steps self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( steps.retrieve, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( steps.list, # pyright: ignore[reportDeprecated], ) ) class AsyncStepsWithRawResponse: def __init__(self, steps: AsyncSteps) -> None: self._steps = steps self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( steps.retrieve, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( steps.list, # pyright: ignore[reportDeprecated], ) ) class StepsWithStreamingResponse: def __init__(self, steps: Steps) -> None: self._steps = steps self.retrieve = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( steps.retrieve, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( steps.list, # pyright: ignore[reportDeprecated], ) ) class AsyncStepsWithStreamingResponse: def __init__(self, steps: AsyncSteps) -> None: self._steps = steps self.retrieve = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( steps.retrieve, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( steps.list, # pyright: ignore[reportDeprecated], ) ) ================================================ FILE: src/openai/resources/beta/threads/threads.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import typing_extensions from typing import Union, Iterable, Optional from functools import partial from typing_extensions import Literal, overload import httpx from .... import _legacy_response from .messages import ( Messages, AsyncMessages, MessagesWithRawResponse, AsyncMessagesWithRawResponse, MessagesWithStreamingResponse, AsyncMessagesWithStreamingResponse, ) from ...._types import NOT_GIVEN, Body, Omit, Query, Headers, NotGiven, omit, not_given from ...._utils import required_args, maybe_transform, async_maybe_transform from .runs.runs import ( Runs, AsyncRuns, RunsWithRawResponse, AsyncRunsWithRawResponse, RunsWithStreamingResponse, AsyncRunsWithStreamingResponse, ) from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ...._streaming import Stream, AsyncStream from ....types.beta import ( thread_create_params, thread_update_params, thread_create_and_run_params, ) from ...._base_client import make_request_options from ....lib.streaming import ( AssistantEventHandler, AssistantEventHandlerT, AssistantStreamManager, AsyncAssistantEventHandler, AsyncAssistantEventHandlerT, AsyncAssistantStreamManager, ) from ....types.beta.thread import Thread from ....types.beta.threads.run import Run from ....types.shared.chat_model import ChatModel from ....types.beta.thread_deleted import ThreadDeleted from ....types.shared_params.metadata import Metadata from ....types.beta.assistant_tool_param import AssistantToolParam from ....types.beta.assistant_stream_event import AssistantStreamEvent from ....types.beta.assistant_tool_choice_option_param import AssistantToolChoiceOptionParam from ....types.beta.assistant_response_format_option_param import AssistantResponseFormatOptionParam __all__ = ["Threads", "AsyncThreads"] class Threads(SyncAPIResource): """Build Assistants that can call models and use tools.""" @cached_property def runs(self) -> Runs: """Build Assistants that can call models and use tools.""" return Runs(self._client) @cached_property def messages(self) -> Messages: """Build Assistants that can call models and use tools.""" return Messages(self._client) @cached_property def with_raw_response(self) -> ThreadsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return ThreadsWithRawResponse(self) @cached_property def with_streaming_response(self) -> ThreadsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return ThreadsWithStreamingResponse(self) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def create( self, *, messages: Iterable[thread_create_params.Message] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, tool_resources: Optional[thread_create_params.ToolResources] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Thread: """ Create a thread. Args: messages: A list of [messages](https://platform.openai.com/docs/api-reference/messages) to start the thread with. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. tool_resources: A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._post( "/threads", body=maybe_transform( { "messages": messages, "metadata": metadata, "tool_resources": tool_resources, }, thread_create_params.ThreadCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Thread, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def retrieve( self, thread_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Thread: """ Retrieves a thread. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get( f"/threads/{thread_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Thread, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def update( self, thread_id: str, *, metadata: Optional[Metadata] | Omit = omit, tool_resources: Optional[thread_update_params.ToolResources] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Thread: """ Modifies a thread. Args: metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. tool_resources: A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._post( f"/threads/{thread_id}", body=maybe_transform( { "metadata": metadata, "tool_resources": tool_resources, }, thread_update_params.ThreadUpdateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Thread, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def delete( self, thread_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ThreadDeleted: """ Delete a thread. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._delete( f"/threads/{thread_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ThreadDeleted, ) @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def create_and_run( self, *, assistant_id: str, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, stream: Optional[Literal[False]] | Omit = omit, temperature: Optional[float] | Omit = omit, thread: thread_create_and_run_params.Thread | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tool_resources: Optional[thread_create_and_run_params.ToolResources] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[thread_create_and_run_params.TruncationStrategy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run: """ Create a thread and run it in one request. Args: assistant_id: The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to use to execute this run. instructions: Override the default system message of the assistant. This is useful for modifying the behavior on a per-run basis. max_completion_tokens: The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. max_prompt_tokens: The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used. parallel_tool_calls: Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. response_format: Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. stream: If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. thread: Options to create a new thread. If no thread is provided when running a request, an empty thread will be created. tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tools and instead generates a message. `auto` is the default value and means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools before responding to the user. Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. tool_resources: A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. tools: Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. truncation_strategy: Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def create_and_run( self, *, assistant_id: str, stream: Literal[True], instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, thread: thread_create_and_run_params.Thread | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tool_resources: Optional[thread_create_and_run_params.ToolResources] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[thread_create_and_run_params.TruncationStrategy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Stream[AssistantStreamEvent]: """ Create a thread and run it in one request. Args: assistant_id: The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to use to execute this run. stream: If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. instructions: Override the default system message of the assistant. This is useful for modifying the behavior on a per-run basis. max_completion_tokens: The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. max_prompt_tokens: The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used. parallel_tool_calls: Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. response_format: Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. thread: Options to create a new thread. If no thread is provided when running a request, an empty thread will be created. tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tools and instead generates a message. `auto` is the default value and means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools before responding to the user. Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. tool_resources: A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. tools: Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. truncation_strategy: Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def create_and_run( self, *, assistant_id: str, stream: bool, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, thread: thread_create_and_run_params.Thread | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tool_resources: Optional[thread_create_and_run_params.ToolResources] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[thread_create_and_run_params.TruncationStrategy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run | Stream[AssistantStreamEvent]: """ Create a thread and run it in one request. Args: assistant_id: The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to use to execute this run. stream: If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. instructions: Override the default system message of the assistant. This is useful for modifying the behavior on a per-run basis. max_completion_tokens: The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. max_prompt_tokens: The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used. parallel_tool_calls: Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. response_format: Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. thread: Options to create a new thread. If no thread is provided when running a request, an empty thread will be created. tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tools and instead generates a message. `auto` is the default value and means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools before responding to the user. Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. tool_resources: A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. tools: Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. truncation_strategy: Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") @required_args(["assistant_id"], ["assistant_id", "stream"]) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") def create_and_run( self, *, assistant_id: str, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, stream: Optional[Literal[False]] | Literal[True] | Omit = omit, temperature: Optional[float] | Omit = omit, thread: thread_create_and_run_params.Thread | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tool_resources: Optional[thread_create_and_run_params.ToolResources] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[thread_create_and_run_params.TruncationStrategy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run | Stream[AssistantStreamEvent]: extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._post( "/threads/runs", body=maybe_transform( { "assistant_id": assistant_id, "instructions": instructions, "max_completion_tokens": max_completion_tokens, "max_prompt_tokens": max_prompt_tokens, "metadata": metadata, "model": model, "parallel_tool_calls": parallel_tool_calls, "response_format": response_format, "stream": stream, "temperature": temperature, "thread": thread, "tool_choice": tool_choice, "tool_resources": tool_resources, "tools": tools, "top_p": top_p, "truncation_strategy": truncation_strategy, }, thread_create_and_run_params.ThreadCreateAndRunParamsStreaming if stream else thread_create_and_run_params.ThreadCreateAndRunParamsNonStreaming, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, synthesize_event_and_data=True, ), cast_to=Run, stream=stream or False, stream_cls=Stream[AssistantStreamEvent], ) def create_and_run_poll( self, *, assistant_id: str, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, thread: thread_create_and_run_params.Thread | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tool_resources: Optional[thread_create_and_run_params.ToolResources] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[thread_create_and_run_params.TruncationStrategy] | Omit = omit, poll_interval_ms: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Run: """ A helper to create a thread, start a run and then poll for a terminal state. More information on Run lifecycles can be found here: https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps """ run = self.create_and_run( # pyright: ignore[reportDeprecated] assistant_id=assistant_id, instructions=instructions, max_completion_tokens=max_completion_tokens, max_prompt_tokens=max_prompt_tokens, metadata=metadata, model=model, parallel_tool_calls=parallel_tool_calls, response_format=response_format, temperature=temperature, stream=False, thread=thread, tool_resources=tool_resources, tool_choice=tool_choice, truncation_strategy=truncation_strategy, top_p=top_p, tools=tools, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, ) return self.runs.poll(run.id, run.thread_id, extra_headers, extra_query, extra_body, timeout, poll_interval_ms) # pyright: ignore[reportDeprecated] @overload def create_and_run_stream( self, *, assistant_id: str, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, thread: thread_create_and_run_params.Thread | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tool_resources: Optional[thread_create_and_run_params.ToolResources] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[thread_create_and_run_params.TruncationStrategy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AssistantStreamManager[AssistantEventHandler]: """Create a thread and stream the run back""" ... @overload def create_and_run_stream( self, *, assistant_id: str, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, thread: thread_create_and_run_params.Thread | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tool_resources: Optional[thread_create_and_run_params.ToolResources] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[thread_create_and_run_params.TruncationStrategy] | Omit = omit, event_handler: AssistantEventHandlerT, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AssistantStreamManager[AssistantEventHandlerT]: """Create a thread and stream the run back""" ... def create_and_run_stream( self, *, assistant_id: str, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, thread: thread_create_and_run_params.Thread | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tool_resources: Optional[thread_create_and_run_params.ToolResources] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[thread_create_and_run_params.TruncationStrategy] | Omit = omit, event_handler: AssistantEventHandlerT | None = None, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AssistantStreamManager[AssistantEventHandler] | AssistantStreamManager[AssistantEventHandlerT]: """Create a thread and stream the run back""" extra_headers = { "OpenAI-Beta": "assistants=v2", "X-Stainless-Stream-Helper": "threads.create_and_run_stream", "X-Stainless-Custom-Event-Handler": "true" if event_handler else "false", **(extra_headers or {}), } make_request = partial( self._post, "/threads/runs", body=maybe_transform( { "assistant_id": assistant_id, "instructions": instructions, "max_completion_tokens": max_completion_tokens, "max_prompt_tokens": max_prompt_tokens, "metadata": metadata, "model": model, "parallel_tool_calls": parallel_tool_calls, "response_format": response_format, "temperature": temperature, "tool_choice": tool_choice, "stream": True, "thread": thread, "tools": tools, "tool_resources": tool_resources, "truncation_strategy": truncation_strategy, "top_p": top_p, }, thread_create_and_run_params.ThreadCreateAndRunParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Run, stream=True, stream_cls=Stream[AssistantStreamEvent], ) return AssistantStreamManager(make_request, event_handler=event_handler or AssistantEventHandler()) class AsyncThreads(AsyncAPIResource): """Build Assistants that can call models and use tools.""" @cached_property def runs(self) -> AsyncRuns: """Build Assistants that can call models and use tools.""" return AsyncRuns(self._client) @cached_property def messages(self) -> AsyncMessages: """Build Assistants that can call models and use tools.""" return AsyncMessages(self._client) @cached_property def with_raw_response(self) -> AsyncThreadsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncThreadsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncThreadsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncThreadsWithStreamingResponse(self) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def create( self, *, messages: Iterable[thread_create_params.Message] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, tool_resources: Optional[thread_create_params.ToolResources] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Thread: """ Create a thread. Args: messages: A list of [messages](https://platform.openai.com/docs/api-reference/messages) to start the thread with. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. tool_resources: A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._post( "/threads", body=await async_maybe_transform( { "messages": messages, "metadata": metadata, "tool_resources": tool_resources, }, thread_create_params.ThreadCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Thread, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def retrieve( self, thread_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Thread: """ Retrieves a thread. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._get( f"/threads/{thread_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Thread, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def update( self, thread_id: str, *, metadata: Optional[Metadata] | Omit = omit, tool_resources: Optional[thread_update_params.ToolResources] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Thread: """ Modifies a thread. Args: metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. tool_resources: A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._post( f"/threads/{thread_id}", body=await async_maybe_transform( { "metadata": metadata, "tool_resources": tool_resources, }, thread_update_params.ThreadUpdateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Thread, ) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def delete( self, thread_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ThreadDeleted: """ Delete a thread. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not thread_id: raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._delete( f"/threads/{thread_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ThreadDeleted, ) @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def create_and_run( self, *, assistant_id: str, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, stream: Optional[Literal[False]] | Omit = omit, temperature: Optional[float] | Omit = omit, thread: thread_create_and_run_params.Thread | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tool_resources: Optional[thread_create_and_run_params.ToolResources] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[thread_create_and_run_params.TruncationStrategy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run: """ Create a thread and run it in one request. Args: assistant_id: The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to use to execute this run. instructions: Override the default system message of the assistant. This is useful for modifying the behavior on a per-run basis. max_completion_tokens: The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. max_prompt_tokens: The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used. parallel_tool_calls: Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. response_format: Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. stream: If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. thread: Options to create a new thread. If no thread is provided when running a request, an empty thread will be created. tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tools and instead generates a message. `auto` is the default value and means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools before responding to the user. Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. tool_resources: A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. tools: Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. truncation_strategy: Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def create_and_run( self, *, assistant_id: str, stream: Literal[True], instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, thread: thread_create_and_run_params.Thread | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tool_resources: Optional[thread_create_and_run_params.ToolResources] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[thread_create_and_run_params.TruncationStrategy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncStream[AssistantStreamEvent]: """ Create a thread and run it in one request. Args: assistant_id: The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to use to execute this run. stream: If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. instructions: Override the default system message of the assistant. This is useful for modifying the behavior on a per-run basis. max_completion_tokens: The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. max_prompt_tokens: The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used. parallel_tool_calls: Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. response_format: Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. thread: Options to create a new thread. If no thread is provided when running a request, an empty thread will be created. tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tools and instead generates a message. `auto` is the default value and means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools before responding to the user. Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. tool_resources: A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. tools: Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. truncation_strategy: Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def create_and_run( self, *, assistant_id: str, stream: bool, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, thread: thread_create_and_run_params.Thread | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tool_resources: Optional[thread_create_and_run_params.ToolResources] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[thread_create_and_run_params.TruncationStrategy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run | AsyncStream[AssistantStreamEvent]: """ Create a thread and run it in one request. Args: assistant_id: The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to use to execute this run. stream: If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. instructions: Override the default system message of the assistant. This is useful for modifying the behavior on a per-run basis. max_completion_tokens: The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. max_prompt_tokens: The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used. parallel_tool_calls: Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. response_format: Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. thread: Options to create a new thread. If no thread is provided when running a request, an empty thread will be created. tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tools and instead generates a message. `auto` is the default value and means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools before responding to the user. Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. tool_resources: A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. tools: Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. truncation_strategy: Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") @required_args(["assistant_id"], ["assistant_id", "stream"]) @typing_extensions.deprecated("The Assistants API is deprecated in favor of the Responses API") async def create_and_run( self, *, assistant_id: str, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, stream: Optional[Literal[False]] | Literal[True] | Omit = omit, temperature: Optional[float] | Omit = omit, thread: thread_create_and_run_params.Thread | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tool_resources: Optional[thread_create_and_run_params.ToolResources] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[thread_create_and_run_params.TruncationStrategy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Run | AsyncStream[AssistantStreamEvent]: extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._post( "/threads/runs", body=await async_maybe_transform( { "assistant_id": assistant_id, "instructions": instructions, "max_completion_tokens": max_completion_tokens, "max_prompt_tokens": max_prompt_tokens, "metadata": metadata, "model": model, "parallel_tool_calls": parallel_tool_calls, "response_format": response_format, "stream": stream, "temperature": temperature, "thread": thread, "tool_choice": tool_choice, "tool_resources": tool_resources, "tools": tools, "top_p": top_p, "truncation_strategy": truncation_strategy, }, thread_create_and_run_params.ThreadCreateAndRunParamsStreaming if stream else thread_create_and_run_params.ThreadCreateAndRunParamsNonStreaming, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, synthesize_event_and_data=True, ), cast_to=Run, stream=stream or False, stream_cls=AsyncStream[AssistantStreamEvent], ) async def create_and_run_poll( self, *, assistant_id: str, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, thread: thread_create_and_run_params.Thread | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tool_resources: Optional[thread_create_and_run_params.ToolResources] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[thread_create_and_run_params.TruncationStrategy] | Omit = omit, poll_interval_ms: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Run: """ A helper to create a thread, start a run and then poll for a terminal state. More information on Run lifecycles can be found here: https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps """ run = await self.create_and_run( # pyright: ignore[reportDeprecated] assistant_id=assistant_id, instructions=instructions, max_completion_tokens=max_completion_tokens, max_prompt_tokens=max_prompt_tokens, metadata=metadata, model=model, parallel_tool_calls=parallel_tool_calls, response_format=response_format, temperature=temperature, stream=False, thread=thread, tool_resources=tool_resources, tool_choice=tool_choice, truncation_strategy=truncation_strategy, top_p=top_p, tools=tools, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, ) return await self.runs.poll( # pyright: ignore[reportDeprecated] run.id, run.thread_id, extra_headers, extra_query, extra_body, timeout, poll_interval_ms ) @overload def create_and_run_stream( self, *, assistant_id: str, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, thread: thread_create_and_run_params.Thread | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tool_resources: Optional[thread_create_and_run_params.ToolResources] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[thread_create_and_run_params.TruncationStrategy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncAssistantStreamManager[AsyncAssistantEventHandler]: """Create a thread and stream the run back""" ... @overload def create_and_run_stream( self, *, assistant_id: str, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, thread: thread_create_and_run_params.Thread | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tool_resources: Optional[thread_create_and_run_params.ToolResources] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[thread_create_and_run_params.TruncationStrategy] | Omit = omit, event_handler: AsyncAssistantEventHandlerT, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncAssistantStreamManager[AsyncAssistantEventHandlerT]: """Create a thread and stream the run back""" ... def create_and_run_stream( self, *, assistant_id: str, instructions: Optional[str] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_prompt_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: Union[str, ChatModel, None] | Omit = omit, parallel_tool_calls: bool | Omit = omit, response_format: Optional[AssistantResponseFormatOptionParam] | Omit = omit, temperature: Optional[float] | Omit = omit, thread: thread_create_and_run_params.Thread | Omit = omit, tool_choice: Optional[AssistantToolChoiceOptionParam] | Omit = omit, tool_resources: Optional[thread_create_and_run_params.ToolResources] | Omit = omit, tools: Optional[Iterable[AssistantToolParam]] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation_strategy: Optional[thread_create_and_run_params.TruncationStrategy] | Omit = omit, event_handler: AsyncAssistantEventHandlerT | None = None, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> ( AsyncAssistantStreamManager[AsyncAssistantEventHandler] | AsyncAssistantStreamManager[AsyncAssistantEventHandlerT] ): """Create a thread and stream the run back""" extra_headers = { "OpenAI-Beta": "assistants=v2", "X-Stainless-Stream-Helper": "threads.create_and_run_stream", "X-Stainless-Custom-Event-Handler": "true" if event_handler else "false", **(extra_headers or {}), } request = self._post( "/threads/runs", body=maybe_transform( { "assistant_id": assistant_id, "instructions": instructions, "max_completion_tokens": max_completion_tokens, "max_prompt_tokens": max_prompt_tokens, "metadata": metadata, "model": model, "parallel_tool_calls": parallel_tool_calls, "response_format": response_format, "temperature": temperature, "tool_choice": tool_choice, "stream": True, "thread": thread, "tools": tools, "tool_resources": tool_resources, "truncation_strategy": truncation_strategy, "top_p": top_p, }, thread_create_and_run_params.ThreadCreateAndRunParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Run, stream=True, stream_cls=AsyncStream[AssistantStreamEvent], ) return AsyncAssistantStreamManager(request, event_handler=event_handler or AsyncAssistantEventHandler()) class ThreadsWithRawResponse: def __init__(self, threads: Threads) -> None: self._threads = threads self.create = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( threads.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( threads.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( threads.update, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( threads.delete, # pyright: ignore[reportDeprecated], ) ) self.create_and_run = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( threads.create_and_run, # pyright: ignore[reportDeprecated], ) ) @cached_property def runs(self) -> RunsWithRawResponse: """Build Assistants that can call models and use tools.""" return RunsWithRawResponse(self._threads.runs) @cached_property def messages(self) -> MessagesWithRawResponse: """Build Assistants that can call models and use tools.""" return MessagesWithRawResponse(self._threads.messages) class AsyncThreadsWithRawResponse: def __init__(self, threads: AsyncThreads) -> None: self._threads = threads self.create = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( threads.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( threads.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( threads.update, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( threads.delete, # pyright: ignore[reportDeprecated], ) ) self.create_and_run = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( threads.create_and_run, # pyright: ignore[reportDeprecated], ) ) @cached_property def runs(self) -> AsyncRunsWithRawResponse: """Build Assistants that can call models and use tools.""" return AsyncRunsWithRawResponse(self._threads.runs) @cached_property def messages(self) -> AsyncMessagesWithRawResponse: """Build Assistants that can call models and use tools.""" return AsyncMessagesWithRawResponse(self._threads.messages) class ThreadsWithStreamingResponse: def __init__(self, threads: Threads) -> None: self._threads = threads self.create = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( threads.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( threads.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( threads.update, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( threads.delete, # pyright: ignore[reportDeprecated], ) ) self.create_and_run = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( threads.create_and_run, # pyright: ignore[reportDeprecated], ) ) @cached_property def runs(self) -> RunsWithStreamingResponse: """Build Assistants that can call models and use tools.""" return RunsWithStreamingResponse(self._threads.runs) @cached_property def messages(self) -> MessagesWithStreamingResponse: """Build Assistants that can call models and use tools.""" return MessagesWithStreamingResponse(self._threads.messages) class AsyncThreadsWithStreamingResponse: def __init__(self, threads: AsyncThreads) -> None: self._threads = threads self.create = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( threads.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( threads.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( threads.update, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( threads.delete, # pyright: ignore[reportDeprecated], ) ) self.create_and_run = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( threads.create_and_run, # pyright: ignore[reportDeprecated], ) ) @cached_property def runs(self) -> AsyncRunsWithStreamingResponse: """Build Assistants that can call models and use tools.""" return AsyncRunsWithStreamingResponse(self._threads.runs) @cached_property def messages(self) -> AsyncMessagesWithStreamingResponse: """Build Assistants that can call models and use tools.""" return AsyncMessagesWithStreamingResponse(self._threads.messages) ================================================ FILE: src/openai/resources/chat/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .chat import ( Chat, AsyncChat, ChatWithRawResponse, AsyncChatWithRawResponse, ChatWithStreamingResponse, AsyncChatWithStreamingResponse, ) from .completions import ( Completions, AsyncCompletions, CompletionsWithRawResponse, AsyncCompletionsWithRawResponse, CompletionsWithStreamingResponse, AsyncCompletionsWithStreamingResponse, ) __all__ = [ "Completions", "AsyncCompletions", "CompletionsWithRawResponse", "AsyncCompletionsWithRawResponse", "CompletionsWithStreamingResponse", "AsyncCompletionsWithStreamingResponse", "Chat", "AsyncChat", "ChatWithRawResponse", "AsyncChatWithRawResponse", "ChatWithStreamingResponse", "AsyncChatWithStreamingResponse", ] ================================================ FILE: src/openai/resources/chat/chat.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from .completions.completions import ( Completions, AsyncCompletions, CompletionsWithRawResponse, AsyncCompletionsWithRawResponse, CompletionsWithStreamingResponse, AsyncCompletionsWithStreamingResponse, ) __all__ = ["Chat", "AsyncChat"] class Chat(SyncAPIResource): @cached_property def completions(self) -> Completions: """ Given a list of messages comprising a conversation, the model will return a response. """ return Completions(self._client) @cached_property def with_raw_response(self) -> ChatWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return ChatWithRawResponse(self) @cached_property def with_streaming_response(self) -> ChatWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return ChatWithStreamingResponse(self) class AsyncChat(AsyncAPIResource): @cached_property def completions(self) -> AsyncCompletions: """ Given a list of messages comprising a conversation, the model will return a response. """ return AsyncCompletions(self._client) @cached_property def with_raw_response(self) -> AsyncChatWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncChatWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncChatWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncChatWithStreamingResponse(self) class ChatWithRawResponse: def __init__(self, chat: Chat) -> None: self._chat = chat @cached_property def completions(self) -> CompletionsWithRawResponse: """ Given a list of messages comprising a conversation, the model will return a response. """ return CompletionsWithRawResponse(self._chat.completions) class AsyncChatWithRawResponse: def __init__(self, chat: AsyncChat) -> None: self._chat = chat @cached_property def completions(self) -> AsyncCompletionsWithRawResponse: """ Given a list of messages comprising a conversation, the model will return a response. """ return AsyncCompletionsWithRawResponse(self._chat.completions) class ChatWithStreamingResponse: def __init__(self, chat: Chat) -> None: self._chat = chat @cached_property def completions(self) -> CompletionsWithStreamingResponse: """ Given a list of messages comprising a conversation, the model will return a response. """ return CompletionsWithStreamingResponse(self._chat.completions) class AsyncChatWithStreamingResponse: def __init__(self, chat: AsyncChat) -> None: self._chat = chat @cached_property def completions(self) -> AsyncCompletionsWithStreamingResponse: """ Given a list of messages comprising a conversation, the model will return a response. """ return AsyncCompletionsWithStreamingResponse(self._chat.completions) ================================================ FILE: src/openai/resources/chat/completions/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .messages import ( Messages, AsyncMessages, MessagesWithRawResponse, AsyncMessagesWithRawResponse, MessagesWithStreamingResponse, AsyncMessagesWithStreamingResponse, ) from .completions import ( Completions, AsyncCompletions, CompletionsWithRawResponse, AsyncCompletionsWithRawResponse, CompletionsWithStreamingResponse, AsyncCompletionsWithStreamingResponse, ) __all__ = [ "Messages", "AsyncMessages", "MessagesWithRawResponse", "AsyncMessagesWithRawResponse", "MessagesWithStreamingResponse", "AsyncMessagesWithStreamingResponse", "Completions", "AsyncCompletions", "CompletionsWithRawResponse", "AsyncCompletionsWithRawResponse", "CompletionsWithStreamingResponse", "AsyncCompletionsWithStreamingResponse", ] ================================================ FILE: src/openai/resources/chat/completions/completions.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import inspect from typing import Dict, List, Type, Union, Iterable, Optional, cast from functools import partial from typing_extensions import Literal, overload import httpx import pydantic from .... import _legacy_response from .messages import ( Messages, AsyncMessages, MessagesWithRawResponse, AsyncMessagesWithRawResponse, MessagesWithStreamingResponse, AsyncMessagesWithStreamingResponse, ) from ...._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from ...._utils import required_args, maybe_transform, async_maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ...._streaming import Stream, AsyncStream from ....pagination import SyncCursorPage, AsyncCursorPage from ....types.chat import ( ChatCompletionAudioParam, completion_list_params, completion_create_params, completion_update_params, ) from ...._base_client import AsyncPaginator, make_request_options from ....lib._parsing import ( ResponseFormatT, validate_input_tools as _validate_input_tools, parse_chat_completion as _parse_chat_completion, type_to_response_format_param as _type_to_response_format, ) from ....lib.streaming.chat import ChatCompletionStreamManager, AsyncChatCompletionStreamManager from ....types.shared.chat_model import ChatModel from ....types.chat.chat_completion import ChatCompletion from ....types.shared_params.metadata import Metadata from ....types.shared.reasoning_effort import ReasoningEffort from ....types.chat.chat_completion_chunk import ChatCompletionChunk from ....types.chat.parsed_chat_completion import ParsedChatCompletion from ....types.chat.chat_completion_deleted import ChatCompletionDeleted from ....types.chat.chat_completion_audio_param import ChatCompletionAudioParam from ....types.chat.chat_completion_message_param import ChatCompletionMessageParam from ....types.chat.chat_completion_tool_union_param import ChatCompletionToolUnionParam from ....types.chat.chat_completion_stream_options_param import ChatCompletionStreamOptionsParam from ....types.chat.chat_completion_prediction_content_param import ChatCompletionPredictionContentParam from ....types.chat.chat_completion_tool_choice_option_param import ChatCompletionToolChoiceOptionParam __all__ = ["Completions", "AsyncCompletions"] class Completions(SyncAPIResource): """ Given a list of messages comprising a conversation, the model will return a response. """ @cached_property def messages(self) -> Messages: """ Given a list of messages comprising a conversation, the model will return a response. """ return Messages(self._client) @cached_property def with_raw_response(self) -> CompletionsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return CompletionsWithRawResponse(self) @cached_property def with_streaming_response(self) -> CompletionsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return CompletionsWithStreamingResponse(self) def parse( self, *, messages: Iterable[ChatCompletionMessageParam], model: Union[str, ChatModel], audio: Optional[ChatCompletionAudioParam] | Omit = omit, response_format: type[ResponseFormatT] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, function_call: completion_create_params.FunctionCall | Omit = omit, functions: Iterable[completion_create_params.Function] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[bool] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, modalities: Optional[List[Literal["text", "audio"]]] | Omit = omit, n: Optional[int] | Omit = omit, parallel_tool_calls: bool | Omit = omit, prediction: Optional[ChatCompletionPredictionContentParam] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, safety_identifier: str | Omit = omit, seed: Optional[int] | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, store: Optional[bool] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: ChatCompletionToolChoiceOptionParam | Omit = omit, tools: Iterable[ChatCompletionToolUnionParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, verbosity: Optional[Literal["low", "medium", "high"]] | Omit = omit, web_search_options: completion_create_params.WebSearchOptions | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ParsedChatCompletion[ResponseFormatT]: """Wrapper over the `client.chat.completions.create()` method that provides richer integrations with Python specific types & returns a `ParsedChatCompletion` object, which is a subclass of the standard `ChatCompletion` class. You can pass a pydantic model to this method and it will automatically convert the model into a JSON schema, send it to the API and parse the response content back into the given model. This method will also automatically parse `function` tool calls if: - You use the `openai.pydantic_function_tool()` helper method - You mark your tool schema with `"strict": True` Example usage: ```py from pydantic import BaseModel from openai import OpenAI class Step(BaseModel): explanation: str output: str class MathResponse(BaseModel): steps: List[Step] final_answer: str client = OpenAI() completion = client.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[ {"role": "system", "content": "You are a helpful math tutor."}, {"role": "user", "content": "solve 8x + 31 = 2"}, ], response_format=MathResponse, ) message = completion.choices[0].message if message.parsed: print(message.parsed.steps) print("answer: ", message.parsed.final_answer) ``` """ chat_completion_tools = _validate_input_tools(tools) extra_headers = { "X-Stainless-Helper-Method": "chat.completions.parse", **(extra_headers or {}), } def parser(raw_completion: ChatCompletion) -> ParsedChatCompletion[ResponseFormatT]: return _parse_chat_completion( response_format=response_format, chat_completion=raw_completion, input_tools=chat_completion_tools, ) return self._post( "/chat/completions", body=maybe_transform( { "messages": messages, "model": model, "audio": audio, "frequency_penalty": frequency_penalty, "function_call": function_call, "functions": functions, "logit_bias": logit_bias, "logprobs": logprobs, "max_completion_tokens": max_completion_tokens, "max_tokens": max_tokens, "metadata": metadata, "modalities": modalities, "n": n, "parallel_tool_calls": parallel_tool_calls, "prediction": prediction, "presence_penalty": presence_penalty, "prompt_cache_key": prompt_cache_key, "prompt_cache_retention": prompt_cache_retention, "reasoning_effort": reasoning_effort, "response_format": _type_to_response_format(response_format), "safety_identifier": safety_identifier, "seed": seed, "service_tier": service_tier, "stop": stop, "store": store, "stream": False, "stream_options": stream_options, "temperature": temperature, "tool_choice": tool_choice, "tools": tools, "top_logprobs": top_logprobs, "top_p": top_p, "user": user, "verbosity": verbosity, "web_search_options": web_search_options, }, completion_create_params.CompletionCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, post_parser=parser, ), # we turn the `ChatCompletion` instance into a `ParsedChatCompletion` # in the `parser` function above cast_to=cast(Type[ParsedChatCompletion[ResponseFormatT]], ChatCompletion), stream=False, ) @overload def create( self, *, messages: Iterable[ChatCompletionMessageParam], model: Union[str, ChatModel], audio: Optional[ChatCompletionAudioParam] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, function_call: completion_create_params.FunctionCall | Omit = omit, functions: Iterable[completion_create_params.Function] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[bool] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, modalities: Optional[List[Literal["text", "audio"]]] | Omit = omit, n: Optional[int] | Omit = omit, parallel_tool_calls: bool | Omit = omit, prediction: Optional[ChatCompletionPredictionContentParam] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: completion_create_params.ResponseFormat | Omit = omit, safety_identifier: str | Omit = omit, seed: Optional[int] | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, store: Optional[bool] | Omit = omit, stream: Optional[Literal[False]] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: ChatCompletionToolChoiceOptionParam | Omit = omit, tools: Iterable[ChatCompletionToolUnionParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, verbosity: Optional[Literal["low", "medium", "high"]] | Omit = omit, web_search_options: completion_create_params.WebSearchOptions | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatCompletion: """ **Starting a new project?** We recommend trying [Responses](https://platform.openai.com/docs/api-reference/responses) to take advantage of the latest OpenAI platform features. Compare [Chat Completions with Responses](https://platform.openai.com/docs/guides/responses-vs-chat-completions?api-mode=responses). --- Creates a model response for the given chat conversation. Learn more in the [text generation](https://platform.openai.com/docs/guides/text-generation), [vision](https://platform.openai.com/docs/guides/vision), and [audio](https://platform.openai.com/docs/guides/audio) guides. Parameter support can differ depending on the model used to generate the response, particularly for newer reasoning models. Parameters that are only supported for reasoning models are noted below. For the current state of unsupported parameters in reasoning models, [refer to the reasoning guide](https://platform.openai.com/docs/guides/reasoning). Returns a chat completion object, or a streamed sequence of chat completion chunk objects if the request is streamed. Args: messages: A list of messages comprising the conversation so far. Depending on the [model](https://platform.openai.com/docs/models) you use, different message types (modalities) are supported, like [text](https://platform.openai.com/docs/guides/text-generation), [images](https://platform.openai.com/docs/guides/vision), and [audio](https://platform.openai.com/docs/guides/audio). model: Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. audio: Parameters for audio output. Required when audio output is requested with `modalities: ["audio"]`. [Learn more](https://platform.openai.com/docs/guides/audio). frequency_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. function_call: Deprecated in favor of `tool_choice`. Controls which (if any) function is called by the model. `none` means the model will not call a function and instead generates a message. `auto` means the model can pick between generating a message or calling a function. Specifying a particular function via `{"name": "my_function"}` forces the model to call that function. `none` is the default when no functions are present. `auto` is the default if functions are present. functions: Deprecated in favor of `tools`. A list of functions the model may generate JSON inputs for. logit_bias: Modify the likelihood of specified tokens appearing in the completion. Accepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. logprobs: Whether to return log probabilities of the output tokens or not. If true, returns the log probabilities of each output token returned in the `content` of `message`. max_completion_tokens: An upper bound for the number of tokens that can be generated for a completion, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). max_tokens: The maximum number of [tokens](/tokenizer) that can be generated in the chat completion. This value can be used to control [costs](https://openai.com/api/pricing/) for text generated via API. This value is now deprecated in favor of `max_completion_tokens`, and is not compatible with [o-series models](https://platform.openai.com/docs/guides/reasoning). metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. modalities: Output types that you would like the model to generate. Most models are capable of generating text, which is the default: `["text"]` The `gpt-4o-audio-preview` model can also be used to [generate audio](https://platform.openai.com/docs/guides/audio). To request that this model generate both text and audio responses, you can use: `["text", "audio"]` n: How many chat completion choices to generate for each input message. Note that you will be charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to minimize costs. parallel_tool_calls: Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. prediction: Static predicted output content, such as the content of a text file that is being regenerated. presence_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. prompt_cache_key: Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://platform.openai.com/docs/guides/prompt-caching). prompt_cache_retention: The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). reasoning_effort: Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. response_format: An object specifying the format that the model must output. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables the older JSON mode, which ensures the message the model generates is valid JSON. Using `json_schema` is preferred for models that support it. safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). seed: This feature is in Beta. If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result. Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend. service_tier: Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier. - When not set, the default behavior is 'auto'. When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. stop: Not supported with latest reasoning models `o3` and `o4-mini`. Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence. store: Whether or not to store the output of this chat completion request for use in our [model distillation](https://platform.openai.com/docs/guides/distillation) or [evals](https://platform.openai.com/docs/guides/evals) products. Supports text and image inputs. Note: image inputs over 8MB will be dropped. stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/chat/streaming) for more information, along with the [streaming responses](https://platform.openai.com/docs/guides/streaming-responses) guide for more information on how to handle the streaming events. stream_options: Options for streaming response. Only set this when you set `stream: true`. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tool and instead generates a message. `auto` means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools. Specifying a particular tool via `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. `none` is the default when no tools are present. `auto` is the default if tools are present. tools: A list of tools the model may call. You can provide either [custom tools](https://platform.openai.com/docs/guides/function-calling#custom-tools) or [function tools](https://platform.openai.com/docs/guides/function-calling). top_logprobs: An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. `logprobs` must be set to `true` if this parameter is used. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. user: This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations. A stable identifier for your end-users. Used to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). verbosity: Constrains the verbosity of the model's response. Lower values will result in more concise responses, while higher values will result in more verbose responses. Currently supported values are `low`, `medium`, and `high`. web_search_options: This tool searches the web for relevant results to use in a response. Learn more about the [web search tool](https://platform.openai.com/docs/guides/tools-web-search?api-mode=chat). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload def create( self, *, messages: Iterable[ChatCompletionMessageParam], model: Union[str, ChatModel], stream: Literal[True], audio: Optional[ChatCompletionAudioParam] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, function_call: completion_create_params.FunctionCall | Omit = omit, functions: Iterable[completion_create_params.Function] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[bool] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, modalities: Optional[List[Literal["text", "audio"]]] | Omit = omit, n: Optional[int] | Omit = omit, parallel_tool_calls: bool | Omit = omit, prediction: Optional[ChatCompletionPredictionContentParam] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: completion_create_params.ResponseFormat | Omit = omit, safety_identifier: str | Omit = omit, seed: Optional[int] | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, store: Optional[bool] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: ChatCompletionToolChoiceOptionParam | Omit = omit, tools: Iterable[ChatCompletionToolUnionParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, verbosity: Optional[Literal["low", "medium", "high"]] | Omit = omit, web_search_options: completion_create_params.WebSearchOptions | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Stream[ChatCompletionChunk]: """ **Starting a new project?** We recommend trying [Responses](https://platform.openai.com/docs/api-reference/responses) to take advantage of the latest OpenAI platform features. Compare [Chat Completions with Responses](https://platform.openai.com/docs/guides/responses-vs-chat-completions?api-mode=responses). --- Creates a model response for the given chat conversation. Learn more in the [text generation](https://platform.openai.com/docs/guides/text-generation), [vision](https://platform.openai.com/docs/guides/vision), and [audio](https://platform.openai.com/docs/guides/audio) guides. Parameter support can differ depending on the model used to generate the response, particularly for newer reasoning models. Parameters that are only supported for reasoning models are noted below. For the current state of unsupported parameters in reasoning models, [refer to the reasoning guide](https://platform.openai.com/docs/guides/reasoning). Returns a chat completion object, or a streamed sequence of chat completion chunk objects if the request is streamed. Args: messages: A list of messages comprising the conversation so far. Depending on the [model](https://platform.openai.com/docs/models) you use, different message types (modalities) are supported, like [text](https://platform.openai.com/docs/guides/text-generation), [images](https://platform.openai.com/docs/guides/vision), and [audio](https://platform.openai.com/docs/guides/audio). model: Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/chat/streaming) for more information, along with the [streaming responses](https://platform.openai.com/docs/guides/streaming-responses) guide for more information on how to handle the streaming events. audio: Parameters for audio output. Required when audio output is requested with `modalities: ["audio"]`. [Learn more](https://platform.openai.com/docs/guides/audio). frequency_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. function_call: Deprecated in favor of `tool_choice`. Controls which (if any) function is called by the model. `none` means the model will not call a function and instead generates a message. `auto` means the model can pick between generating a message or calling a function. Specifying a particular function via `{"name": "my_function"}` forces the model to call that function. `none` is the default when no functions are present. `auto` is the default if functions are present. functions: Deprecated in favor of `tools`. A list of functions the model may generate JSON inputs for. logit_bias: Modify the likelihood of specified tokens appearing in the completion. Accepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. logprobs: Whether to return log probabilities of the output tokens or not. If true, returns the log probabilities of each output token returned in the `content` of `message`. max_completion_tokens: An upper bound for the number of tokens that can be generated for a completion, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). max_tokens: The maximum number of [tokens](/tokenizer) that can be generated in the chat completion. This value can be used to control [costs](https://openai.com/api/pricing/) for text generated via API. This value is now deprecated in favor of `max_completion_tokens`, and is not compatible with [o-series models](https://platform.openai.com/docs/guides/reasoning). metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. modalities: Output types that you would like the model to generate. Most models are capable of generating text, which is the default: `["text"]` The `gpt-4o-audio-preview` model can also be used to [generate audio](https://platform.openai.com/docs/guides/audio). To request that this model generate both text and audio responses, you can use: `["text", "audio"]` n: How many chat completion choices to generate for each input message. Note that you will be charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to minimize costs. parallel_tool_calls: Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. prediction: Static predicted output content, such as the content of a text file that is being regenerated. presence_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. prompt_cache_key: Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://platform.openai.com/docs/guides/prompt-caching). prompt_cache_retention: The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). reasoning_effort: Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. response_format: An object specifying the format that the model must output. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables the older JSON mode, which ensures the message the model generates is valid JSON. Using `json_schema` is preferred for models that support it. safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). seed: This feature is in Beta. If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result. Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend. service_tier: Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier. - When not set, the default behavior is 'auto'. When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. stop: Not supported with latest reasoning models `o3` and `o4-mini`. Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence. store: Whether or not to store the output of this chat completion request for use in our [model distillation](https://platform.openai.com/docs/guides/distillation) or [evals](https://platform.openai.com/docs/guides/evals) products. Supports text and image inputs. Note: image inputs over 8MB will be dropped. stream_options: Options for streaming response. Only set this when you set `stream: true`. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tool and instead generates a message. `auto` means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools. Specifying a particular tool via `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. `none` is the default when no tools are present. `auto` is the default if tools are present. tools: A list of tools the model may call. You can provide either [custom tools](https://platform.openai.com/docs/guides/function-calling#custom-tools) or [function tools](https://platform.openai.com/docs/guides/function-calling). top_logprobs: An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. `logprobs` must be set to `true` if this parameter is used. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. user: This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations. A stable identifier for your end-users. Used to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). verbosity: Constrains the verbosity of the model's response. Lower values will result in more concise responses, while higher values will result in more verbose responses. Currently supported values are `low`, `medium`, and `high`. web_search_options: This tool searches the web for relevant results to use in a response. Learn more about the [web search tool](https://platform.openai.com/docs/guides/tools-web-search?api-mode=chat). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload def create( self, *, messages: Iterable[ChatCompletionMessageParam], model: Union[str, ChatModel], stream: bool, audio: Optional[ChatCompletionAudioParam] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, function_call: completion_create_params.FunctionCall | Omit = omit, functions: Iterable[completion_create_params.Function] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[bool] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, modalities: Optional[List[Literal["text", "audio"]]] | Omit = omit, n: Optional[int] | Omit = omit, parallel_tool_calls: bool | Omit = omit, prediction: Optional[ChatCompletionPredictionContentParam] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: completion_create_params.ResponseFormat | Omit = omit, safety_identifier: str | Omit = omit, seed: Optional[int] | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, store: Optional[bool] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: ChatCompletionToolChoiceOptionParam | Omit = omit, tools: Iterable[ChatCompletionToolUnionParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, verbosity: Optional[Literal["low", "medium", "high"]] | Omit = omit, web_search_options: completion_create_params.WebSearchOptions | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatCompletion | Stream[ChatCompletionChunk]: """ **Starting a new project?** We recommend trying [Responses](https://platform.openai.com/docs/api-reference/responses) to take advantage of the latest OpenAI platform features. Compare [Chat Completions with Responses](https://platform.openai.com/docs/guides/responses-vs-chat-completions?api-mode=responses). --- Creates a model response for the given chat conversation. Learn more in the [text generation](https://platform.openai.com/docs/guides/text-generation), [vision](https://platform.openai.com/docs/guides/vision), and [audio](https://platform.openai.com/docs/guides/audio) guides. Parameter support can differ depending on the model used to generate the response, particularly for newer reasoning models. Parameters that are only supported for reasoning models are noted below. For the current state of unsupported parameters in reasoning models, [refer to the reasoning guide](https://platform.openai.com/docs/guides/reasoning). Returns a chat completion object, or a streamed sequence of chat completion chunk objects if the request is streamed. Args: messages: A list of messages comprising the conversation so far. Depending on the [model](https://platform.openai.com/docs/models) you use, different message types (modalities) are supported, like [text](https://platform.openai.com/docs/guides/text-generation), [images](https://platform.openai.com/docs/guides/vision), and [audio](https://platform.openai.com/docs/guides/audio). model: Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/chat/streaming) for more information, along with the [streaming responses](https://platform.openai.com/docs/guides/streaming-responses) guide for more information on how to handle the streaming events. audio: Parameters for audio output. Required when audio output is requested with `modalities: ["audio"]`. [Learn more](https://platform.openai.com/docs/guides/audio). frequency_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. function_call: Deprecated in favor of `tool_choice`. Controls which (if any) function is called by the model. `none` means the model will not call a function and instead generates a message. `auto` means the model can pick between generating a message or calling a function. Specifying a particular function via `{"name": "my_function"}` forces the model to call that function. `none` is the default when no functions are present. `auto` is the default if functions are present. functions: Deprecated in favor of `tools`. A list of functions the model may generate JSON inputs for. logit_bias: Modify the likelihood of specified tokens appearing in the completion. Accepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. logprobs: Whether to return log probabilities of the output tokens or not. If true, returns the log probabilities of each output token returned in the `content` of `message`. max_completion_tokens: An upper bound for the number of tokens that can be generated for a completion, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). max_tokens: The maximum number of [tokens](/tokenizer) that can be generated in the chat completion. This value can be used to control [costs](https://openai.com/api/pricing/) for text generated via API. This value is now deprecated in favor of `max_completion_tokens`, and is not compatible with [o-series models](https://platform.openai.com/docs/guides/reasoning). metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. modalities: Output types that you would like the model to generate. Most models are capable of generating text, which is the default: `["text"]` The `gpt-4o-audio-preview` model can also be used to [generate audio](https://platform.openai.com/docs/guides/audio). To request that this model generate both text and audio responses, you can use: `["text", "audio"]` n: How many chat completion choices to generate for each input message. Note that you will be charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to minimize costs. parallel_tool_calls: Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. prediction: Static predicted output content, such as the content of a text file that is being regenerated. presence_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. prompt_cache_key: Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://platform.openai.com/docs/guides/prompt-caching). prompt_cache_retention: The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). reasoning_effort: Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. response_format: An object specifying the format that the model must output. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables the older JSON mode, which ensures the message the model generates is valid JSON. Using `json_schema` is preferred for models that support it. safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). seed: This feature is in Beta. If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result. Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend. service_tier: Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier. - When not set, the default behavior is 'auto'. When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. stop: Not supported with latest reasoning models `o3` and `o4-mini`. Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence. store: Whether or not to store the output of this chat completion request for use in our [model distillation](https://platform.openai.com/docs/guides/distillation) or [evals](https://platform.openai.com/docs/guides/evals) products. Supports text and image inputs. Note: image inputs over 8MB will be dropped. stream_options: Options for streaming response. Only set this when you set `stream: true`. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tool and instead generates a message. `auto` means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools. Specifying a particular tool via `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. `none` is the default when no tools are present. `auto` is the default if tools are present. tools: A list of tools the model may call. You can provide either [custom tools](https://platform.openai.com/docs/guides/function-calling#custom-tools) or [function tools](https://platform.openai.com/docs/guides/function-calling). top_logprobs: An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. `logprobs` must be set to `true` if this parameter is used. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. user: This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations. A stable identifier for your end-users. Used to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). verbosity: Constrains the verbosity of the model's response. Lower values will result in more concise responses, while higher values will result in more verbose responses. Currently supported values are `low`, `medium`, and `high`. web_search_options: This tool searches the web for relevant results to use in a response. Learn more about the [web search tool](https://platform.openai.com/docs/guides/tools-web-search?api-mode=chat). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @required_args(["messages", "model"], ["messages", "model", "stream"]) def create( self, *, messages: Iterable[ChatCompletionMessageParam], model: Union[str, ChatModel], audio: Optional[ChatCompletionAudioParam] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, function_call: completion_create_params.FunctionCall | Omit = omit, functions: Iterable[completion_create_params.Function] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[bool] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, modalities: Optional[List[Literal["text", "audio"]]] | Omit = omit, n: Optional[int] | Omit = omit, parallel_tool_calls: bool | Omit = omit, prediction: Optional[ChatCompletionPredictionContentParam] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: completion_create_params.ResponseFormat | Omit = omit, safety_identifier: str | Omit = omit, seed: Optional[int] | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, store: Optional[bool] | Omit = omit, stream: Optional[Literal[False]] | Literal[True] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: ChatCompletionToolChoiceOptionParam | Omit = omit, tools: Iterable[ChatCompletionToolUnionParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, verbosity: Optional[Literal["low", "medium", "high"]] | Omit = omit, web_search_options: completion_create_params.WebSearchOptions | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatCompletion | Stream[ChatCompletionChunk]: validate_response_format(response_format) return self._post( "/chat/completions", body=maybe_transform( { "messages": messages, "model": model, "audio": audio, "frequency_penalty": frequency_penalty, "function_call": function_call, "functions": functions, "logit_bias": logit_bias, "logprobs": logprobs, "max_completion_tokens": max_completion_tokens, "max_tokens": max_tokens, "metadata": metadata, "modalities": modalities, "n": n, "parallel_tool_calls": parallel_tool_calls, "prediction": prediction, "presence_penalty": presence_penalty, "prompt_cache_key": prompt_cache_key, "prompt_cache_retention": prompt_cache_retention, "reasoning_effort": reasoning_effort, "response_format": response_format, "safety_identifier": safety_identifier, "seed": seed, "service_tier": service_tier, "stop": stop, "store": store, "stream": stream, "stream_options": stream_options, "temperature": temperature, "tool_choice": tool_choice, "tools": tools, "top_logprobs": top_logprobs, "top_p": top_p, "user": user, "verbosity": verbosity, "web_search_options": web_search_options, }, completion_create_params.CompletionCreateParamsStreaming if stream else completion_create_params.CompletionCreateParamsNonStreaming, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ChatCompletion, stream=stream or False, stream_cls=Stream[ChatCompletionChunk], ) def retrieve( self, completion_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatCompletion: """Get a stored chat completion. Only Chat Completions that have been created with the `store` parameter set to `true` will be returned. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not completion_id: raise ValueError(f"Expected a non-empty value for `completion_id` but received {completion_id!r}") return self._get( f"/chat/completions/{completion_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ChatCompletion, ) def update( self, completion_id: str, *, metadata: Optional[Metadata], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatCompletion: """Modify a stored chat completion. Only Chat Completions that have been created with the `store` parameter set to `true` can be modified. Currently, the only supported modification is to update the `metadata` field. Args: metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not completion_id: raise ValueError(f"Expected a non-empty value for `completion_id` but received {completion_id!r}") return self._post( f"/chat/completions/{completion_id}", body=maybe_transform({"metadata": metadata}, completion_update_params.CompletionUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ChatCompletion, ) def list( self, *, after: str | Omit = omit, limit: int | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: str | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[ChatCompletion]: """List stored Chat Completions. Only Chat Completions that have been stored with the `store` parameter set to `true` will be returned. Args: after: Identifier for the last chat completion from the previous pagination request. limit: Number of Chat Completions to retrieve. metadata: A list of metadata keys to filter the Chat Completions by. Example: `metadata[key1]=value1&metadata[key2]=value2` model: The model used to generate the Chat Completions. order: Sort order for Chat Completions by timestamp. Use `asc` for ascending order or `desc` for descending order. Defaults to `asc`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._get_api_list( "/chat/completions", page=SyncCursorPage[ChatCompletion], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "metadata": metadata, "model": model, "order": order, }, completion_list_params.CompletionListParams, ), ), model=ChatCompletion, ) def delete( self, completion_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatCompletionDeleted: """Delete a stored chat completion. Only Chat Completions that have been created with the `store` parameter set to `true` can be deleted. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not completion_id: raise ValueError(f"Expected a non-empty value for `completion_id` but received {completion_id!r}") return self._delete( f"/chat/completions/{completion_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ChatCompletionDeleted, ) def stream( self, *, messages: Iterable[ChatCompletionMessageParam], model: Union[str, ChatModel], audio: Optional[ChatCompletionAudioParam] | Omit = omit, response_format: completion_create_params.ResponseFormat | type[ResponseFormatT] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, function_call: completion_create_params.FunctionCall | Omit = omit, functions: Iterable[completion_create_params.Function] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[bool] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, modalities: Optional[List[Literal["text", "audio"]]] | Omit = omit, n: Optional[int] | Omit = omit, parallel_tool_calls: bool | Omit = omit, prediction: Optional[ChatCompletionPredictionContentParam] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, safety_identifier: str | Omit = omit, seed: Optional[int] | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, store: Optional[bool] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: ChatCompletionToolChoiceOptionParam | Omit = omit, tools: Iterable[ChatCompletionToolUnionParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, verbosity: Optional[Literal["low", "medium", "high"]] | Omit = omit, web_search_options: completion_create_params.WebSearchOptions | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatCompletionStreamManager[ResponseFormatT]: """Wrapper over the `client.chat.completions.create(stream=True)` method that provides a more granular event API and automatic accumulation of each delta. This also supports all of the parsing utilities that `.parse()` does. Unlike `.create(stream=True)`, the `.stream()` method requires usage within a context manager to prevent accidental leakage of the response: ```py with client.chat.completions.stream( model="gpt-4o-2024-08-06", messages=[...], ) as stream: for event in stream: if event.type == "content.delta": print(event.delta, flush=True, end="") ``` When the context manager is entered, a `ChatCompletionStream` instance is returned which, like `.create(stream=True)` is an iterator. The full list of events that are yielded by the iterator are outlined in [these docs](https://github.com/openai/openai-python/blob/main/helpers.md#chat-completions-events). When the context manager exits, the response will be closed, however the `stream` instance is still available outside the context manager. """ extra_headers = { "X-Stainless-Helper-Method": "chat.completions.stream", **(extra_headers or {}), } api_request: partial[Stream[ChatCompletionChunk]] = partial( self.create, messages=messages, model=model, audio=audio, stream=True, response_format=_type_to_response_format(response_format), frequency_penalty=frequency_penalty, function_call=function_call, functions=functions, logit_bias=logit_bias, logprobs=logprobs, max_completion_tokens=max_completion_tokens, max_tokens=max_tokens, metadata=metadata, modalities=modalities, n=n, parallel_tool_calls=parallel_tool_calls, prediction=prediction, presence_penalty=presence_penalty, prompt_cache_key=prompt_cache_key, prompt_cache_retention=prompt_cache_retention, reasoning_effort=reasoning_effort, safety_identifier=safety_identifier, seed=seed, service_tier=service_tier, store=store, stop=stop, stream_options=stream_options, temperature=temperature, tool_choice=tool_choice, tools=tools, top_logprobs=top_logprobs, top_p=top_p, user=user, verbosity=verbosity, web_search_options=web_search_options, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, ) return ChatCompletionStreamManager( api_request, response_format=response_format, input_tools=tools, ) class AsyncCompletions(AsyncAPIResource): """ Given a list of messages comprising a conversation, the model will return a response. """ @cached_property def messages(self) -> AsyncMessages: """ Given a list of messages comprising a conversation, the model will return a response. """ return AsyncMessages(self._client) @cached_property def with_raw_response(self) -> AsyncCompletionsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncCompletionsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncCompletionsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncCompletionsWithStreamingResponse(self) async def parse( self, *, messages: Iterable[ChatCompletionMessageParam], model: Union[str, ChatModel], audio: Optional[ChatCompletionAudioParam] | Omit = omit, response_format: type[ResponseFormatT] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, function_call: completion_create_params.FunctionCall | Omit = omit, functions: Iterable[completion_create_params.Function] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[bool] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, modalities: Optional[List[Literal["text", "audio"]]] | Omit = omit, n: Optional[int] | Omit = omit, parallel_tool_calls: bool | Omit = omit, prediction: Optional[ChatCompletionPredictionContentParam] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, safety_identifier: str | Omit = omit, seed: Optional[int] | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, store: Optional[bool] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: ChatCompletionToolChoiceOptionParam | Omit = omit, tools: Iterable[ChatCompletionToolUnionParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, verbosity: Optional[Literal["low", "medium", "high"]] | Omit = omit, web_search_options: completion_create_params.WebSearchOptions | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ParsedChatCompletion[ResponseFormatT]: """Wrapper over the `client.chat.completions.create()` method that provides richer integrations with Python specific types & returns a `ParsedChatCompletion` object, which is a subclass of the standard `ChatCompletion` class. You can pass a pydantic model to this method and it will automatically convert the model into a JSON schema, send it to the API and parse the response content back into the given model. This method will also automatically parse `function` tool calls if: - You use the `openai.pydantic_function_tool()` helper method - You mark your tool schema with `"strict": True` Example usage: ```py from pydantic import BaseModel from openai import AsyncOpenAI class Step(BaseModel): explanation: str output: str class MathResponse(BaseModel): steps: List[Step] final_answer: str client = AsyncOpenAI() completion = await client.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[ {"role": "system", "content": "You are a helpful math tutor."}, {"role": "user", "content": "solve 8x + 31 = 2"}, ], response_format=MathResponse, ) message = completion.choices[0].message if message.parsed: print(message.parsed.steps) print("answer: ", message.parsed.final_answer) ``` """ _validate_input_tools(tools) extra_headers = { "X-Stainless-Helper-Method": "chat.completions.parse", **(extra_headers or {}), } def parser(raw_completion: ChatCompletion) -> ParsedChatCompletion[ResponseFormatT]: return _parse_chat_completion( response_format=response_format, chat_completion=raw_completion, input_tools=tools, ) return await self._post( "/chat/completions", body=await async_maybe_transform( { "messages": messages, "model": model, "audio": audio, "frequency_penalty": frequency_penalty, "function_call": function_call, "functions": functions, "logit_bias": logit_bias, "logprobs": logprobs, "max_completion_tokens": max_completion_tokens, "max_tokens": max_tokens, "metadata": metadata, "modalities": modalities, "n": n, "parallel_tool_calls": parallel_tool_calls, "prediction": prediction, "presence_penalty": presence_penalty, "prompt_cache_key": prompt_cache_key, "prompt_cache_retention": prompt_cache_retention, "reasoning_effort": reasoning_effort, "response_format": _type_to_response_format(response_format), "safety_identifier": safety_identifier, "seed": seed, "service_tier": service_tier, "store": store, "stop": stop, "stream": False, "stream_options": stream_options, "temperature": temperature, "tool_choice": tool_choice, "tools": tools, "top_logprobs": top_logprobs, "top_p": top_p, "user": user, "verbosity": verbosity, "web_search_options": web_search_options, }, completion_create_params.CompletionCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, post_parser=parser, ), # we turn the `ChatCompletion` instance into a `ParsedChatCompletion` # in the `parser` function above cast_to=cast(Type[ParsedChatCompletion[ResponseFormatT]], ChatCompletion), stream=False, ) @overload async def create( self, *, messages: Iterable[ChatCompletionMessageParam], model: Union[str, ChatModel], audio: Optional[ChatCompletionAudioParam] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, function_call: completion_create_params.FunctionCall | Omit = omit, functions: Iterable[completion_create_params.Function] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[bool] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, modalities: Optional[List[Literal["text", "audio"]]] | Omit = omit, n: Optional[int] | Omit = omit, parallel_tool_calls: bool | Omit = omit, prediction: Optional[ChatCompletionPredictionContentParam] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: completion_create_params.ResponseFormat | Omit = omit, safety_identifier: str | Omit = omit, seed: Optional[int] | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, store: Optional[bool] | Omit = omit, stream: Optional[Literal[False]] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: ChatCompletionToolChoiceOptionParam | Omit = omit, tools: Iterable[ChatCompletionToolUnionParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, verbosity: Optional[Literal["low", "medium", "high"]] | Omit = omit, web_search_options: completion_create_params.WebSearchOptions | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatCompletion: """ **Starting a new project?** We recommend trying [Responses](https://platform.openai.com/docs/api-reference/responses) to take advantage of the latest OpenAI platform features. Compare [Chat Completions with Responses](https://platform.openai.com/docs/guides/responses-vs-chat-completions?api-mode=responses). --- Creates a model response for the given chat conversation. Learn more in the [text generation](https://platform.openai.com/docs/guides/text-generation), [vision](https://platform.openai.com/docs/guides/vision), and [audio](https://platform.openai.com/docs/guides/audio) guides. Parameter support can differ depending on the model used to generate the response, particularly for newer reasoning models. Parameters that are only supported for reasoning models are noted below. For the current state of unsupported parameters in reasoning models, [refer to the reasoning guide](https://platform.openai.com/docs/guides/reasoning). Returns a chat completion object, or a streamed sequence of chat completion chunk objects if the request is streamed. Args: messages: A list of messages comprising the conversation so far. Depending on the [model](https://platform.openai.com/docs/models) you use, different message types (modalities) are supported, like [text](https://platform.openai.com/docs/guides/text-generation), [images](https://platform.openai.com/docs/guides/vision), and [audio](https://platform.openai.com/docs/guides/audio). model: Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. audio: Parameters for audio output. Required when audio output is requested with `modalities: ["audio"]`. [Learn more](https://platform.openai.com/docs/guides/audio). frequency_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. function_call: Deprecated in favor of `tool_choice`. Controls which (if any) function is called by the model. `none` means the model will not call a function and instead generates a message. `auto` means the model can pick between generating a message or calling a function. Specifying a particular function via `{"name": "my_function"}` forces the model to call that function. `none` is the default when no functions are present. `auto` is the default if functions are present. functions: Deprecated in favor of `tools`. A list of functions the model may generate JSON inputs for. logit_bias: Modify the likelihood of specified tokens appearing in the completion. Accepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. logprobs: Whether to return log probabilities of the output tokens or not. If true, returns the log probabilities of each output token returned in the `content` of `message`. max_completion_tokens: An upper bound for the number of tokens that can be generated for a completion, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). max_tokens: The maximum number of [tokens](/tokenizer) that can be generated in the chat completion. This value can be used to control [costs](https://openai.com/api/pricing/) for text generated via API. This value is now deprecated in favor of `max_completion_tokens`, and is not compatible with [o-series models](https://platform.openai.com/docs/guides/reasoning). metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. modalities: Output types that you would like the model to generate. Most models are capable of generating text, which is the default: `["text"]` The `gpt-4o-audio-preview` model can also be used to [generate audio](https://platform.openai.com/docs/guides/audio). To request that this model generate both text and audio responses, you can use: `["text", "audio"]` n: How many chat completion choices to generate for each input message. Note that you will be charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to minimize costs. parallel_tool_calls: Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. prediction: Static predicted output content, such as the content of a text file that is being regenerated. presence_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. prompt_cache_key: Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://platform.openai.com/docs/guides/prompt-caching). prompt_cache_retention: The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). reasoning_effort: Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. response_format: An object specifying the format that the model must output. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables the older JSON mode, which ensures the message the model generates is valid JSON. Using `json_schema` is preferred for models that support it. safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). seed: This feature is in Beta. If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result. Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend. service_tier: Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier. - When not set, the default behavior is 'auto'. When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. stop: Not supported with latest reasoning models `o3` and `o4-mini`. Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence. store: Whether or not to store the output of this chat completion request for use in our [model distillation](https://platform.openai.com/docs/guides/distillation) or [evals](https://platform.openai.com/docs/guides/evals) products. Supports text and image inputs. Note: image inputs over 8MB will be dropped. stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/chat/streaming) for more information, along with the [streaming responses](https://platform.openai.com/docs/guides/streaming-responses) guide for more information on how to handle the streaming events. stream_options: Options for streaming response. Only set this when you set `stream: true`. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tool and instead generates a message. `auto` means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools. Specifying a particular tool via `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. `none` is the default when no tools are present. `auto` is the default if tools are present. tools: A list of tools the model may call. You can provide either [custom tools](https://platform.openai.com/docs/guides/function-calling#custom-tools) or [function tools](https://platform.openai.com/docs/guides/function-calling). top_logprobs: An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. `logprobs` must be set to `true` if this parameter is used. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. user: This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations. A stable identifier for your end-users. Used to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). verbosity: Constrains the verbosity of the model's response. Lower values will result in more concise responses, while higher values will result in more verbose responses. Currently supported values are `low`, `medium`, and `high`. web_search_options: This tool searches the web for relevant results to use in a response. Learn more about the [web search tool](https://platform.openai.com/docs/guides/tools-web-search?api-mode=chat). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload async def create( self, *, messages: Iterable[ChatCompletionMessageParam], model: Union[str, ChatModel], stream: Literal[True], audio: Optional[ChatCompletionAudioParam] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, function_call: completion_create_params.FunctionCall | Omit = omit, functions: Iterable[completion_create_params.Function] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[bool] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, modalities: Optional[List[Literal["text", "audio"]]] | Omit = omit, n: Optional[int] | Omit = omit, parallel_tool_calls: bool | Omit = omit, prediction: Optional[ChatCompletionPredictionContentParam] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: completion_create_params.ResponseFormat | Omit = omit, safety_identifier: str | Omit = omit, seed: Optional[int] | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, store: Optional[bool] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: ChatCompletionToolChoiceOptionParam | Omit = omit, tools: Iterable[ChatCompletionToolUnionParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, verbosity: Optional[Literal["low", "medium", "high"]] | Omit = omit, web_search_options: completion_create_params.WebSearchOptions | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncStream[ChatCompletionChunk]: """ **Starting a new project?** We recommend trying [Responses](https://platform.openai.com/docs/api-reference/responses) to take advantage of the latest OpenAI platform features. Compare [Chat Completions with Responses](https://platform.openai.com/docs/guides/responses-vs-chat-completions?api-mode=responses). --- Creates a model response for the given chat conversation. Learn more in the [text generation](https://platform.openai.com/docs/guides/text-generation), [vision](https://platform.openai.com/docs/guides/vision), and [audio](https://platform.openai.com/docs/guides/audio) guides. Parameter support can differ depending on the model used to generate the response, particularly for newer reasoning models. Parameters that are only supported for reasoning models are noted below. For the current state of unsupported parameters in reasoning models, [refer to the reasoning guide](https://platform.openai.com/docs/guides/reasoning). Returns a chat completion object, or a streamed sequence of chat completion chunk objects if the request is streamed. Args: messages: A list of messages comprising the conversation so far. Depending on the [model](https://platform.openai.com/docs/models) you use, different message types (modalities) are supported, like [text](https://platform.openai.com/docs/guides/text-generation), [images](https://platform.openai.com/docs/guides/vision), and [audio](https://platform.openai.com/docs/guides/audio). model: Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/chat/streaming) for more information, along with the [streaming responses](https://platform.openai.com/docs/guides/streaming-responses) guide for more information on how to handle the streaming events. audio: Parameters for audio output. Required when audio output is requested with `modalities: ["audio"]`. [Learn more](https://platform.openai.com/docs/guides/audio). frequency_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. function_call: Deprecated in favor of `tool_choice`. Controls which (if any) function is called by the model. `none` means the model will not call a function and instead generates a message. `auto` means the model can pick between generating a message or calling a function. Specifying a particular function via `{"name": "my_function"}` forces the model to call that function. `none` is the default when no functions are present. `auto` is the default if functions are present. functions: Deprecated in favor of `tools`. A list of functions the model may generate JSON inputs for. logit_bias: Modify the likelihood of specified tokens appearing in the completion. Accepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. logprobs: Whether to return log probabilities of the output tokens or not. If true, returns the log probabilities of each output token returned in the `content` of `message`. max_completion_tokens: An upper bound for the number of tokens that can be generated for a completion, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). max_tokens: The maximum number of [tokens](/tokenizer) that can be generated in the chat completion. This value can be used to control [costs](https://openai.com/api/pricing/) for text generated via API. This value is now deprecated in favor of `max_completion_tokens`, and is not compatible with [o-series models](https://platform.openai.com/docs/guides/reasoning). metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. modalities: Output types that you would like the model to generate. Most models are capable of generating text, which is the default: `["text"]` The `gpt-4o-audio-preview` model can also be used to [generate audio](https://platform.openai.com/docs/guides/audio). To request that this model generate both text and audio responses, you can use: `["text", "audio"]` n: How many chat completion choices to generate for each input message. Note that you will be charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to minimize costs. parallel_tool_calls: Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. prediction: Static predicted output content, such as the content of a text file that is being regenerated. presence_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. prompt_cache_key: Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://platform.openai.com/docs/guides/prompt-caching). prompt_cache_retention: The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). reasoning_effort: Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. response_format: An object specifying the format that the model must output. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables the older JSON mode, which ensures the message the model generates is valid JSON. Using `json_schema` is preferred for models that support it. safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). seed: This feature is in Beta. If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result. Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend. service_tier: Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier. - When not set, the default behavior is 'auto'. When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. stop: Not supported with latest reasoning models `o3` and `o4-mini`. Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence. store: Whether or not to store the output of this chat completion request for use in our [model distillation](https://platform.openai.com/docs/guides/distillation) or [evals](https://platform.openai.com/docs/guides/evals) products. Supports text and image inputs. Note: image inputs over 8MB will be dropped. stream_options: Options for streaming response. Only set this when you set `stream: true`. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tool and instead generates a message. `auto` means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools. Specifying a particular tool via `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. `none` is the default when no tools are present. `auto` is the default if tools are present. tools: A list of tools the model may call. You can provide either [custom tools](https://platform.openai.com/docs/guides/function-calling#custom-tools) or [function tools](https://platform.openai.com/docs/guides/function-calling). top_logprobs: An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. `logprobs` must be set to `true` if this parameter is used. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. user: This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations. A stable identifier for your end-users. Used to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). verbosity: Constrains the verbosity of the model's response. Lower values will result in more concise responses, while higher values will result in more verbose responses. Currently supported values are `low`, `medium`, and `high`. web_search_options: This tool searches the web for relevant results to use in a response. Learn more about the [web search tool](https://platform.openai.com/docs/guides/tools-web-search?api-mode=chat). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload async def create( self, *, messages: Iterable[ChatCompletionMessageParam], model: Union[str, ChatModel], stream: bool, audio: Optional[ChatCompletionAudioParam] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, function_call: completion_create_params.FunctionCall | Omit = omit, functions: Iterable[completion_create_params.Function] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[bool] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, modalities: Optional[List[Literal["text", "audio"]]] | Omit = omit, n: Optional[int] | Omit = omit, parallel_tool_calls: bool | Omit = omit, prediction: Optional[ChatCompletionPredictionContentParam] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: completion_create_params.ResponseFormat | Omit = omit, safety_identifier: str | Omit = omit, seed: Optional[int] | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, store: Optional[bool] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: ChatCompletionToolChoiceOptionParam | Omit = omit, tools: Iterable[ChatCompletionToolUnionParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, verbosity: Optional[Literal["low", "medium", "high"]] | Omit = omit, web_search_options: completion_create_params.WebSearchOptions | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatCompletion | AsyncStream[ChatCompletionChunk]: """ **Starting a new project?** We recommend trying [Responses](https://platform.openai.com/docs/api-reference/responses) to take advantage of the latest OpenAI platform features. Compare [Chat Completions with Responses](https://platform.openai.com/docs/guides/responses-vs-chat-completions?api-mode=responses). --- Creates a model response for the given chat conversation. Learn more in the [text generation](https://platform.openai.com/docs/guides/text-generation), [vision](https://platform.openai.com/docs/guides/vision), and [audio](https://platform.openai.com/docs/guides/audio) guides. Parameter support can differ depending on the model used to generate the response, particularly for newer reasoning models. Parameters that are only supported for reasoning models are noted below. For the current state of unsupported parameters in reasoning models, [refer to the reasoning guide](https://platform.openai.com/docs/guides/reasoning). Returns a chat completion object, or a streamed sequence of chat completion chunk objects if the request is streamed. Args: messages: A list of messages comprising the conversation so far. Depending on the [model](https://platform.openai.com/docs/models) you use, different message types (modalities) are supported, like [text](https://platform.openai.com/docs/guides/text-generation), [images](https://platform.openai.com/docs/guides/vision), and [audio](https://platform.openai.com/docs/guides/audio). model: Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/chat/streaming) for more information, along with the [streaming responses](https://platform.openai.com/docs/guides/streaming-responses) guide for more information on how to handle the streaming events. audio: Parameters for audio output. Required when audio output is requested with `modalities: ["audio"]`. [Learn more](https://platform.openai.com/docs/guides/audio). frequency_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. function_call: Deprecated in favor of `tool_choice`. Controls which (if any) function is called by the model. `none` means the model will not call a function and instead generates a message. `auto` means the model can pick between generating a message or calling a function. Specifying a particular function via `{"name": "my_function"}` forces the model to call that function. `none` is the default when no functions are present. `auto` is the default if functions are present. functions: Deprecated in favor of `tools`. A list of functions the model may generate JSON inputs for. logit_bias: Modify the likelihood of specified tokens appearing in the completion. Accepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. logprobs: Whether to return log probabilities of the output tokens or not. If true, returns the log probabilities of each output token returned in the `content` of `message`. max_completion_tokens: An upper bound for the number of tokens that can be generated for a completion, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). max_tokens: The maximum number of [tokens](/tokenizer) that can be generated in the chat completion. This value can be used to control [costs](https://openai.com/api/pricing/) for text generated via API. This value is now deprecated in favor of `max_completion_tokens`, and is not compatible with [o-series models](https://platform.openai.com/docs/guides/reasoning). metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. modalities: Output types that you would like the model to generate. Most models are capable of generating text, which is the default: `["text"]` The `gpt-4o-audio-preview` model can also be used to [generate audio](https://platform.openai.com/docs/guides/audio). To request that this model generate both text and audio responses, you can use: `["text", "audio"]` n: How many chat completion choices to generate for each input message. Note that you will be charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to minimize costs. parallel_tool_calls: Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. prediction: Static predicted output content, such as the content of a text file that is being regenerated. presence_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. prompt_cache_key: Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://platform.openai.com/docs/guides/prompt-caching). prompt_cache_retention: The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). reasoning_effort: Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. response_format: An object specifying the format that the model must output. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables the older JSON mode, which ensures the message the model generates is valid JSON. Using `json_schema` is preferred for models that support it. safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). seed: This feature is in Beta. If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result. Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend. service_tier: Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier. - When not set, the default behavior is 'auto'. When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. stop: Not supported with latest reasoning models `o3` and `o4-mini`. Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence. store: Whether or not to store the output of this chat completion request for use in our [model distillation](https://platform.openai.com/docs/guides/distillation) or [evals](https://platform.openai.com/docs/guides/evals) products. Supports text and image inputs. Note: image inputs over 8MB will be dropped. stream_options: Options for streaming response. Only set this when you set `stream: true`. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tool and instead generates a message. `auto` means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools. Specifying a particular tool via `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. `none` is the default when no tools are present. `auto` is the default if tools are present. tools: A list of tools the model may call. You can provide either [custom tools](https://platform.openai.com/docs/guides/function-calling#custom-tools) or [function tools](https://platform.openai.com/docs/guides/function-calling). top_logprobs: An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. `logprobs` must be set to `true` if this parameter is used. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. user: This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations. A stable identifier for your end-users. Used to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). verbosity: Constrains the verbosity of the model's response. Lower values will result in more concise responses, while higher values will result in more verbose responses. Currently supported values are `low`, `medium`, and `high`. web_search_options: This tool searches the web for relevant results to use in a response. Learn more about the [web search tool](https://platform.openai.com/docs/guides/tools-web-search?api-mode=chat). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @required_args(["messages", "model"], ["messages", "model", "stream"]) async def create( self, *, messages: Iterable[ChatCompletionMessageParam], model: Union[str, ChatModel], audio: Optional[ChatCompletionAudioParam] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, function_call: completion_create_params.FunctionCall | Omit = omit, functions: Iterable[completion_create_params.Function] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[bool] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, modalities: Optional[List[Literal["text", "audio"]]] | Omit = omit, n: Optional[int] | Omit = omit, parallel_tool_calls: bool | Omit = omit, prediction: Optional[ChatCompletionPredictionContentParam] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, response_format: completion_create_params.ResponseFormat | Omit = omit, safety_identifier: str | Omit = omit, seed: Optional[int] | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, store: Optional[bool] | Omit = omit, stream: Optional[Literal[False]] | Literal[True] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: ChatCompletionToolChoiceOptionParam | Omit = omit, tools: Iterable[ChatCompletionToolUnionParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, verbosity: Optional[Literal["low", "medium", "high"]] | Omit = omit, web_search_options: completion_create_params.WebSearchOptions | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatCompletion | AsyncStream[ChatCompletionChunk]: validate_response_format(response_format) return await self._post( "/chat/completions", body=await async_maybe_transform( { "messages": messages, "model": model, "audio": audio, "frequency_penalty": frequency_penalty, "function_call": function_call, "functions": functions, "logit_bias": logit_bias, "logprobs": logprobs, "max_completion_tokens": max_completion_tokens, "max_tokens": max_tokens, "metadata": metadata, "modalities": modalities, "n": n, "parallel_tool_calls": parallel_tool_calls, "prediction": prediction, "presence_penalty": presence_penalty, "prompt_cache_key": prompt_cache_key, "prompt_cache_retention": prompt_cache_retention, "reasoning_effort": reasoning_effort, "response_format": response_format, "safety_identifier": safety_identifier, "seed": seed, "service_tier": service_tier, "stop": stop, "store": store, "stream": stream, "stream_options": stream_options, "temperature": temperature, "tool_choice": tool_choice, "tools": tools, "top_logprobs": top_logprobs, "top_p": top_p, "user": user, "verbosity": verbosity, "web_search_options": web_search_options, }, completion_create_params.CompletionCreateParamsStreaming if stream else completion_create_params.CompletionCreateParamsNonStreaming, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ChatCompletion, stream=stream or False, stream_cls=AsyncStream[ChatCompletionChunk], ) async def retrieve( self, completion_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatCompletion: """Get a stored chat completion. Only Chat Completions that have been created with the `store` parameter set to `true` will be returned. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not completion_id: raise ValueError(f"Expected a non-empty value for `completion_id` but received {completion_id!r}") return await self._get( f"/chat/completions/{completion_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ChatCompletion, ) async def update( self, completion_id: str, *, metadata: Optional[Metadata], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatCompletion: """Modify a stored chat completion. Only Chat Completions that have been created with the `store` parameter set to `true` can be modified. Currently, the only supported modification is to update the `metadata` field. Args: metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not completion_id: raise ValueError(f"Expected a non-empty value for `completion_id` but received {completion_id!r}") return await self._post( f"/chat/completions/{completion_id}", body=await async_maybe_transform({"metadata": metadata}, completion_update_params.CompletionUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ChatCompletion, ) def list( self, *, after: str | Omit = omit, limit: int | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: str | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[ChatCompletion, AsyncCursorPage[ChatCompletion]]: """List stored Chat Completions. Only Chat Completions that have been stored with the `store` parameter set to `true` will be returned. Args: after: Identifier for the last chat completion from the previous pagination request. limit: Number of Chat Completions to retrieve. metadata: A list of metadata keys to filter the Chat Completions by. Example: `metadata[key1]=value1&metadata[key2]=value2` model: The model used to generate the Chat Completions. order: Sort order for Chat Completions by timestamp. Use `asc` for ascending order or `desc` for descending order. Defaults to `asc`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._get_api_list( "/chat/completions", page=AsyncCursorPage[ChatCompletion], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "metadata": metadata, "model": model, "order": order, }, completion_list_params.CompletionListParams, ), ), model=ChatCompletion, ) async def delete( self, completion_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatCompletionDeleted: """Delete a stored chat completion. Only Chat Completions that have been created with the `store` parameter set to `true` can be deleted. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not completion_id: raise ValueError(f"Expected a non-empty value for `completion_id` but received {completion_id!r}") return await self._delete( f"/chat/completions/{completion_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ChatCompletionDeleted, ) def stream( self, *, messages: Iterable[ChatCompletionMessageParam], model: Union[str, ChatModel], audio: Optional[ChatCompletionAudioParam] | Omit = omit, response_format: completion_create_params.ResponseFormat | type[ResponseFormatT] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, function_call: completion_create_params.FunctionCall | Omit = omit, functions: Iterable[completion_create_params.Function] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[bool] | Omit = omit, max_completion_tokens: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, modalities: Optional[List[Literal["text", "audio"]]] | Omit = omit, n: Optional[int] | Omit = omit, parallel_tool_calls: bool | Omit = omit, prediction: Optional[ChatCompletionPredictionContentParam] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning_effort: Optional[ReasoningEffort] | Omit = omit, safety_identifier: str | Omit = omit, seed: Optional[int] | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, store: Optional[bool] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, temperature: Optional[float] | Omit = omit, tool_choice: ChatCompletionToolChoiceOptionParam | Omit = omit, tools: Iterable[ChatCompletionToolUnionParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, verbosity: Optional[Literal["low", "medium", "high"]] | Omit = omit, web_search_options: completion_create_params.WebSearchOptions | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncChatCompletionStreamManager[ResponseFormatT]: """Wrapper over the `client.chat.completions.create(stream=True)` method that provides a more granular event API and automatic accumulation of each delta. This also supports all of the parsing utilities that `.parse()` does. Unlike `.create(stream=True)`, the `.stream()` method requires usage within a context manager to prevent accidental leakage of the response: ```py async with client.chat.completions.stream( model="gpt-4o-2024-08-06", messages=[...], ) as stream: async for event in stream: if event.type == "content.delta": print(event.delta, flush=True, end="") ``` When the context manager is entered, an `AsyncChatCompletionStream` instance is returned which, like `.create(stream=True)` is an async iterator. The full list of events that are yielded by the iterator are outlined in [these docs](https://github.com/openai/openai-python/blob/main/helpers.md#chat-completions-events). When the context manager exits, the response will be closed, however the `stream` instance is still available outside the context manager. """ _validate_input_tools(tools) extra_headers = { "X-Stainless-Helper-Method": "chat.completions.stream", **(extra_headers or {}), } api_request = self.create( messages=messages, model=model, audio=audio, stream=True, response_format=_type_to_response_format(response_format), frequency_penalty=frequency_penalty, function_call=function_call, functions=functions, logit_bias=logit_bias, logprobs=logprobs, max_completion_tokens=max_completion_tokens, max_tokens=max_tokens, metadata=metadata, modalities=modalities, n=n, parallel_tool_calls=parallel_tool_calls, prediction=prediction, presence_penalty=presence_penalty, prompt_cache_key=prompt_cache_key, prompt_cache_retention=prompt_cache_retention, reasoning_effort=reasoning_effort, safety_identifier=safety_identifier, seed=seed, service_tier=service_tier, stop=stop, store=store, stream_options=stream_options, temperature=temperature, tool_choice=tool_choice, tools=tools, top_logprobs=top_logprobs, top_p=top_p, user=user, verbosity=verbosity, web_search_options=web_search_options, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, ) return AsyncChatCompletionStreamManager( api_request, response_format=response_format, input_tools=tools, ) class CompletionsWithRawResponse: def __init__(self, completions: Completions) -> None: self._completions = completions self.parse = _legacy_response.to_raw_response_wrapper( completions.parse, ) self.create = _legacy_response.to_raw_response_wrapper( completions.create, ) self.retrieve = _legacy_response.to_raw_response_wrapper( completions.retrieve, ) self.update = _legacy_response.to_raw_response_wrapper( completions.update, ) self.list = _legacy_response.to_raw_response_wrapper( completions.list, ) self.delete = _legacy_response.to_raw_response_wrapper( completions.delete, ) @cached_property def messages(self) -> MessagesWithRawResponse: """ Given a list of messages comprising a conversation, the model will return a response. """ return MessagesWithRawResponse(self._completions.messages) class AsyncCompletionsWithRawResponse: def __init__(self, completions: AsyncCompletions) -> None: self._completions = completions self.parse = _legacy_response.async_to_raw_response_wrapper( completions.parse, ) self.create = _legacy_response.async_to_raw_response_wrapper( completions.create, ) self.retrieve = _legacy_response.async_to_raw_response_wrapper( completions.retrieve, ) self.update = _legacy_response.async_to_raw_response_wrapper( completions.update, ) self.list = _legacy_response.async_to_raw_response_wrapper( completions.list, ) self.delete = _legacy_response.async_to_raw_response_wrapper( completions.delete, ) @cached_property def messages(self) -> AsyncMessagesWithRawResponse: """ Given a list of messages comprising a conversation, the model will return a response. """ return AsyncMessagesWithRawResponse(self._completions.messages) class CompletionsWithStreamingResponse: def __init__(self, completions: Completions) -> None: self._completions = completions self.parse = to_streamed_response_wrapper( completions.parse, ) self.create = to_streamed_response_wrapper( completions.create, ) self.retrieve = to_streamed_response_wrapper( completions.retrieve, ) self.update = to_streamed_response_wrapper( completions.update, ) self.list = to_streamed_response_wrapper( completions.list, ) self.delete = to_streamed_response_wrapper( completions.delete, ) @cached_property def messages(self) -> MessagesWithStreamingResponse: """ Given a list of messages comprising a conversation, the model will return a response. """ return MessagesWithStreamingResponse(self._completions.messages) class AsyncCompletionsWithStreamingResponse: def __init__(self, completions: AsyncCompletions) -> None: self._completions = completions self.parse = async_to_streamed_response_wrapper( completions.parse, ) self.create = async_to_streamed_response_wrapper( completions.create, ) self.retrieve = async_to_streamed_response_wrapper( completions.retrieve, ) self.update = async_to_streamed_response_wrapper( completions.update, ) self.list = async_to_streamed_response_wrapper( completions.list, ) self.delete = async_to_streamed_response_wrapper( completions.delete, ) @cached_property def messages(self) -> AsyncMessagesWithStreamingResponse: """ Given a list of messages comprising a conversation, the model will return a response. """ return AsyncMessagesWithStreamingResponse(self._completions.messages) def validate_response_format(response_format: object) -> None: if inspect.isclass(response_format) and issubclass(response_format, pydantic.BaseModel): raise TypeError( "You tried to pass a `BaseModel` class to `chat.completions.create()`; You must use `chat.completions.parse()` instead" ) ================================================ FILE: src/openai/resources/chat/completions/messages.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal import httpx from .... import _legacy_response from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ...._utils import maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ....pagination import SyncCursorPage, AsyncCursorPage from ...._base_client import AsyncPaginator, make_request_options from ....types.chat.completions import message_list_params from ....types.chat.chat_completion_store_message import ChatCompletionStoreMessage __all__ = ["Messages", "AsyncMessages"] class Messages(SyncAPIResource): """ Given a list of messages comprising a conversation, the model will return a response. """ @cached_property def with_raw_response(self) -> MessagesWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return MessagesWithRawResponse(self) @cached_property def with_streaming_response(self) -> MessagesWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return MessagesWithStreamingResponse(self) def list( self, completion_id: str, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[ChatCompletionStoreMessage]: """Get the messages in a stored chat completion. Only Chat Completions that have been created with the `store` parameter set to `true` will be returned. Args: after: Identifier for the last message from the previous pagination request. limit: Number of messages to retrieve. order: Sort order for messages by timestamp. Use `asc` for ascending order or `desc` for descending order. Defaults to `asc`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not completion_id: raise ValueError(f"Expected a non-empty value for `completion_id` but received {completion_id!r}") return self._get_api_list( f"/chat/completions/{completion_id}/messages", page=SyncCursorPage[ChatCompletionStoreMessage], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, }, message_list_params.MessageListParams, ), ), model=ChatCompletionStoreMessage, ) class AsyncMessages(AsyncAPIResource): """ Given a list of messages comprising a conversation, the model will return a response. """ @cached_property def with_raw_response(self) -> AsyncMessagesWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncMessagesWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncMessagesWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncMessagesWithStreamingResponse(self) def list( self, completion_id: str, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[ChatCompletionStoreMessage, AsyncCursorPage[ChatCompletionStoreMessage]]: """Get the messages in a stored chat completion. Only Chat Completions that have been created with the `store` parameter set to `true` will be returned. Args: after: Identifier for the last message from the previous pagination request. limit: Number of messages to retrieve. order: Sort order for messages by timestamp. Use `asc` for ascending order or `desc` for descending order. Defaults to `asc`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not completion_id: raise ValueError(f"Expected a non-empty value for `completion_id` but received {completion_id!r}") return self._get_api_list( f"/chat/completions/{completion_id}/messages", page=AsyncCursorPage[ChatCompletionStoreMessage], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, }, message_list_params.MessageListParams, ), ), model=ChatCompletionStoreMessage, ) class MessagesWithRawResponse: def __init__(self, messages: Messages) -> None: self._messages = messages self.list = _legacy_response.to_raw_response_wrapper( messages.list, ) class AsyncMessagesWithRawResponse: def __init__(self, messages: AsyncMessages) -> None: self._messages = messages self.list = _legacy_response.async_to_raw_response_wrapper( messages.list, ) class MessagesWithStreamingResponse: def __init__(self, messages: Messages) -> None: self._messages = messages self.list = to_streamed_response_wrapper( messages.list, ) class AsyncMessagesWithStreamingResponse: def __init__(self, messages: AsyncMessages) -> None: self._messages = messages self.list = async_to_streamed_response_wrapper( messages.list, ) ================================================ FILE: src/openai/resources/completions.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Union, Iterable, Optional from typing_extensions import Literal, overload import httpx from .. import _legacy_response from ..types import completion_create_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from .._utils import required_args, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from .._streaming import Stream, AsyncStream from .._base_client import ( make_request_options, ) from ..types.completion import Completion from ..types.chat.chat_completion_stream_options_param import ChatCompletionStreamOptionsParam __all__ = ["Completions", "AsyncCompletions"] class Completions(SyncAPIResource): """ Given a prompt, the model will return one or more predicted completions, and can also return the probabilities of alternative tokens at each position. """ @cached_property def with_raw_response(self) -> CompletionsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return CompletionsWithRawResponse(self) @cached_property def with_streaming_response(self) -> CompletionsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return CompletionsWithStreamingResponse(self) @overload def create( self, *, model: Union[str, Literal["gpt-3.5-turbo-instruct", "davinci-002", "babbage-002"]], prompt: Union[str, SequenceNotStr[str], Iterable[int], Iterable[Iterable[int]], None], best_of: Optional[int] | Omit = omit, echo: Optional[bool] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, n: Optional[int] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, seed: Optional[int] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, stream: Optional[Literal[False]] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, suffix: Optional[str] | Omit = omit, temperature: Optional[float] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Completion: """ Creates a completion for the provided prompt and parameters. Returns a completion object, or a sequence of completion objects if the request is streamed. Args: model: ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models) for descriptions of them. prompt: The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of token arrays. Note that <|endoftext|> is the document separator that the model sees during training, so if a prompt is not specified the model will generate as if from the beginning of a new document. best_of: Generates `best_of` completions server-side and returns the "best" (the one with the highest log probability per token). Results cannot be streamed. When used with `n`, `best_of` controls the number of candidate completions and `n` specifies how many to return – `best_of` must be greater than `n`. **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. echo: Echo back the prompt in addition to the completion frequency_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation) logit_bias: Modify the likelihood of specified tokens appearing in the completion. Accepts a JSON object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) to convert text to token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token from being generated. logprobs: Include the log probabilities on the `logprobs` most likely output tokens, as well the chosen tokens. For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` elements in the response. The maximum value for `logprobs` is 5. max_tokens: The maximum number of [tokens](/tokenizer) that can be generated in the completion. The token count of your prompt plus `max_tokens` cannot exceed the model's context length. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens. n: How many completions to generate for each prompt. **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. presence_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation) seed: If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result. Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend. stop: Not supported with latest reasoning models `o3` and `o4-mini`. Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence. stream: Whether to stream back partial progress. If set, tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message. [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). stream_options: Options for streaming response. Only set this when you set `stream: true`. suffix: The suffix that comes after a completion of inserted text. This parameter is only supported for `gpt-3.5-turbo-instruct`. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload def create( self, *, model: Union[str, Literal["gpt-3.5-turbo-instruct", "davinci-002", "babbage-002"]], prompt: Union[str, SequenceNotStr[str], Iterable[int], Iterable[Iterable[int]], None], stream: Literal[True], best_of: Optional[int] | Omit = omit, echo: Optional[bool] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, n: Optional[int] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, seed: Optional[int] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, suffix: Optional[str] | Omit = omit, temperature: Optional[float] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Stream[Completion]: """ Creates a completion for the provided prompt and parameters. Returns a completion object, or a sequence of completion objects if the request is streamed. Args: model: ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models) for descriptions of them. prompt: The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of token arrays. Note that <|endoftext|> is the document separator that the model sees during training, so if a prompt is not specified the model will generate as if from the beginning of a new document. stream: Whether to stream back partial progress. If set, tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message. [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). best_of: Generates `best_of` completions server-side and returns the "best" (the one with the highest log probability per token). Results cannot be streamed. When used with `n`, `best_of` controls the number of candidate completions and `n` specifies how many to return – `best_of` must be greater than `n`. **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. echo: Echo back the prompt in addition to the completion frequency_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation) logit_bias: Modify the likelihood of specified tokens appearing in the completion. Accepts a JSON object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) to convert text to token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token from being generated. logprobs: Include the log probabilities on the `logprobs` most likely output tokens, as well the chosen tokens. For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` elements in the response. The maximum value for `logprobs` is 5. max_tokens: The maximum number of [tokens](/tokenizer) that can be generated in the completion. The token count of your prompt plus `max_tokens` cannot exceed the model's context length. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens. n: How many completions to generate for each prompt. **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. presence_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation) seed: If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result. Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend. stop: Not supported with latest reasoning models `o3` and `o4-mini`. Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence. stream_options: Options for streaming response. Only set this when you set `stream: true`. suffix: The suffix that comes after a completion of inserted text. This parameter is only supported for `gpt-3.5-turbo-instruct`. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload def create( self, *, model: Union[str, Literal["gpt-3.5-turbo-instruct", "davinci-002", "babbage-002"]], prompt: Union[str, SequenceNotStr[str], Iterable[int], Iterable[Iterable[int]], None], stream: bool, best_of: Optional[int] | Omit = omit, echo: Optional[bool] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, n: Optional[int] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, seed: Optional[int] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, suffix: Optional[str] | Omit = omit, temperature: Optional[float] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Completion | Stream[Completion]: """ Creates a completion for the provided prompt and parameters. Returns a completion object, or a sequence of completion objects if the request is streamed. Args: model: ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models) for descriptions of them. prompt: The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of token arrays. Note that <|endoftext|> is the document separator that the model sees during training, so if a prompt is not specified the model will generate as if from the beginning of a new document. stream: Whether to stream back partial progress. If set, tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message. [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). best_of: Generates `best_of` completions server-side and returns the "best" (the one with the highest log probability per token). Results cannot be streamed. When used with `n`, `best_of` controls the number of candidate completions and `n` specifies how many to return – `best_of` must be greater than `n`. **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. echo: Echo back the prompt in addition to the completion frequency_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation) logit_bias: Modify the likelihood of specified tokens appearing in the completion. Accepts a JSON object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) to convert text to token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token from being generated. logprobs: Include the log probabilities on the `logprobs` most likely output tokens, as well the chosen tokens. For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` elements in the response. The maximum value for `logprobs` is 5. max_tokens: The maximum number of [tokens](/tokenizer) that can be generated in the completion. The token count of your prompt plus `max_tokens` cannot exceed the model's context length. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens. n: How many completions to generate for each prompt. **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. presence_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation) seed: If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result. Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend. stop: Not supported with latest reasoning models `o3` and `o4-mini`. Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence. stream_options: Options for streaming response. Only set this when you set `stream: true`. suffix: The suffix that comes after a completion of inserted text. This parameter is only supported for `gpt-3.5-turbo-instruct`. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @required_args(["model", "prompt"], ["model", "prompt", "stream"]) def create( self, *, model: Union[str, Literal["gpt-3.5-turbo-instruct", "davinci-002", "babbage-002"]], prompt: Union[str, SequenceNotStr[str], Iterable[int], Iterable[Iterable[int]], None], best_of: Optional[int] | Omit = omit, echo: Optional[bool] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, n: Optional[int] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, seed: Optional[int] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, stream: Optional[Literal[False]] | Literal[True] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, suffix: Optional[str] | Omit = omit, temperature: Optional[float] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Completion | Stream[Completion]: return self._post( "/completions", body=maybe_transform( { "model": model, "prompt": prompt, "best_of": best_of, "echo": echo, "frequency_penalty": frequency_penalty, "logit_bias": logit_bias, "logprobs": logprobs, "max_tokens": max_tokens, "n": n, "presence_penalty": presence_penalty, "seed": seed, "stop": stop, "stream": stream, "stream_options": stream_options, "suffix": suffix, "temperature": temperature, "top_p": top_p, "user": user, }, completion_create_params.CompletionCreateParamsStreaming if stream else completion_create_params.CompletionCreateParamsNonStreaming, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Completion, stream=stream or False, stream_cls=Stream[Completion], ) class AsyncCompletions(AsyncAPIResource): """ Given a prompt, the model will return one or more predicted completions, and can also return the probabilities of alternative tokens at each position. """ @cached_property def with_raw_response(self) -> AsyncCompletionsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncCompletionsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncCompletionsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncCompletionsWithStreamingResponse(self) @overload async def create( self, *, model: Union[str, Literal["gpt-3.5-turbo-instruct", "davinci-002", "babbage-002"]], prompt: Union[str, SequenceNotStr[str], Iterable[int], Iterable[Iterable[int]], None], best_of: Optional[int] | Omit = omit, echo: Optional[bool] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, n: Optional[int] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, seed: Optional[int] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, stream: Optional[Literal[False]] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, suffix: Optional[str] | Omit = omit, temperature: Optional[float] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Completion: """ Creates a completion for the provided prompt and parameters. Returns a completion object, or a sequence of completion objects if the request is streamed. Args: model: ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models) for descriptions of them. prompt: The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of token arrays. Note that <|endoftext|> is the document separator that the model sees during training, so if a prompt is not specified the model will generate as if from the beginning of a new document. best_of: Generates `best_of` completions server-side and returns the "best" (the one with the highest log probability per token). Results cannot be streamed. When used with `n`, `best_of` controls the number of candidate completions and `n` specifies how many to return – `best_of` must be greater than `n`. **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. echo: Echo back the prompt in addition to the completion frequency_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation) logit_bias: Modify the likelihood of specified tokens appearing in the completion. Accepts a JSON object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) to convert text to token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token from being generated. logprobs: Include the log probabilities on the `logprobs` most likely output tokens, as well the chosen tokens. For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` elements in the response. The maximum value for `logprobs` is 5. max_tokens: The maximum number of [tokens](/tokenizer) that can be generated in the completion. The token count of your prompt plus `max_tokens` cannot exceed the model's context length. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens. n: How many completions to generate for each prompt. **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. presence_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation) seed: If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result. Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend. stop: Not supported with latest reasoning models `o3` and `o4-mini`. Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence. stream: Whether to stream back partial progress. If set, tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message. [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). stream_options: Options for streaming response. Only set this when you set `stream: true`. suffix: The suffix that comes after a completion of inserted text. This parameter is only supported for `gpt-3.5-turbo-instruct`. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload async def create( self, *, model: Union[str, Literal["gpt-3.5-turbo-instruct", "davinci-002", "babbage-002"]], prompt: Union[str, SequenceNotStr[str], Iterable[int], Iterable[Iterable[int]], None], stream: Literal[True], best_of: Optional[int] | Omit = omit, echo: Optional[bool] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, n: Optional[int] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, seed: Optional[int] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, suffix: Optional[str] | Omit = omit, temperature: Optional[float] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncStream[Completion]: """ Creates a completion for the provided prompt and parameters. Returns a completion object, or a sequence of completion objects if the request is streamed. Args: model: ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models) for descriptions of them. prompt: The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of token arrays. Note that <|endoftext|> is the document separator that the model sees during training, so if a prompt is not specified the model will generate as if from the beginning of a new document. stream: Whether to stream back partial progress. If set, tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message. [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). best_of: Generates `best_of` completions server-side and returns the "best" (the one with the highest log probability per token). Results cannot be streamed. When used with `n`, `best_of` controls the number of candidate completions and `n` specifies how many to return – `best_of` must be greater than `n`. **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. echo: Echo back the prompt in addition to the completion frequency_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation) logit_bias: Modify the likelihood of specified tokens appearing in the completion. Accepts a JSON object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) to convert text to token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token from being generated. logprobs: Include the log probabilities on the `logprobs` most likely output tokens, as well the chosen tokens. For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` elements in the response. The maximum value for `logprobs` is 5. max_tokens: The maximum number of [tokens](/tokenizer) that can be generated in the completion. The token count of your prompt plus `max_tokens` cannot exceed the model's context length. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens. n: How many completions to generate for each prompt. **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. presence_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation) seed: If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result. Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend. stop: Not supported with latest reasoning models `o3` and `o4-mini`. Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence. stream_options: Options for streaming response. Only set this when you set `stream: true`. suffix: The suffix that comes after a completion of inserted text. This parameter is only supported for `gpt-3.5-turbo-instruct`. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload async def create( self, *, model: Union[str, Literal["gpt-3.5-turbo-instruct", "davinci-002", "babbage-002"]], prompt: Union[str, SequenceNotStr[str], Iterable[int], Iterable[Iterable[int]], None], stream: bool, best_of: Optional[int] | Omit = omit, echo: Optional[bool] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, n: Optional[int] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, seed: Optional[int] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, suffix: Optional[str] | Omit = omit, temperature: Optional[float] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Completion | AsyncStream[Completion]: """ Creates a completion for the provided prompt and parameters. Returns a completion object, or a sequence of completion objects if the request is streamed. Args: model: ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models) for descriptions of them. prompt: The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of token arrays. Note that <|endoftext|> is the document separator that the model sees during training, so if a prompt is not specified the model will generate as if from the beginning of a new document. stream: Whether to stream back partial progress. If set, tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message. [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). best_of: Generates `best_of` completions server-side and returns the "best" (the one with the highest log probability per token). Results cannot be streamed. When used with `n`, `best_of` controls the number of candidate completions and `n` specifies how many to return – `best_of` must be greater than `n`. **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. echo: Echo back the prompt in addition to the completion frequency_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation) logit_bias: Modify the likelihood of specified tokens appearing in the completion. Accepts a JSON object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) to convert text to token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token from being generated. logprobs: Include the log probabilities on the `logprobs` most likely output tokens, as well the chosen tokens. For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` elements in the response. The maximum value for `logprobs` is 5. max_tokens: The maximum number of [tokens](/tokenizer) that can be generated in the completion. The token count of your prompt plus `max_tokens` cannot exceed the model's context length. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens. n: How many completions to generate for each prompt. **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. presence_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation) seed: If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result. Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend. stop: Not supported with latest reasoning models `o3` and `o4-mini`. Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence. stream_options: Options for streaming response. Only set this when you set `stream: true`. suffix: The suffix that comes after a completion of inserted text. This parameter is only supported for `gpt-3.5-turbo-instruct`. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @required_args(["model", "prompt"], ["model", "prompt", "stream"]) async def create( self, *, model: Union[str, Literal["gpt-3.5-turbo-instruct", "davinci-002", "babbage-002"]], prompt: Union[str, SequenceNotStr[str], Iterable[int], Iterable[Iterable[int]], None], best_of: Optional[int] | Omit = omit, echo: Optional[bool] | Omit = omit, frequency_penalty: Optional[float] | Omit = omit, logit_bias: Optional[Dict[str, int]] | Omit = omit, logprobs: Optional[int] | Omit = omit, max_tokens: Optional[int] | Omit = omit, n: Optional[int] | Omit = omit, presence_penalty: Optional[float] | Omit = omit, seed: Optional[int] | Omit = omit, stop: Union[Optional[str], SequenceNotStr[str], None] | Omit = omit, stream: Optional[Literal[False]] | Literal[True] | Omit = omit, stream_options: Optional[ChatCompletionStreamOptionsParam] | Omit = omit, suffix: Optional[str] | Omit = omit, temperature: Optional[float] | Omit = omit, top_p: Optional[float] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Completion | AsyncStream[Completion]: return await self._post( "/completions", body=await async_maybe_transform( { "model": model, "prompt": prompt, "best_of": best_of, "echo": echo, "frequency_penalty": frequency_penalty, "logit_bias": logit_bias, "logprobs": logprobs, "max_tokens": max_tokens, "n": n, "presence_penalty": presence_penalty, "seed": seed, "stop": stop, "stream": stream, "stream_options": stream_options, "suffix": suffix, "temperature": temperature, "top_p": top_p, "user": user, }, completion_create_params.CompletionCreateParamsStreaming if stream else completion_create_params.CompletionCreateParamsNonStreaming, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Completion, stream=stream or False, stream_cls=AsyncStream[Completion], ) class CompletionsWithRawResponse: def __init__(self, completions: Completions) -> None: self._completions = completions self.create = _legacy_response.to_raw_response_wrapper( completions.create, ) class AsyncCompletionsWithRawResponse: def __init__(self, completions: AsyncCompletions) -> None: self._completions = completions self.create = _legacy_response.async_to_raw_response_wrapper( completions.create, ) class CompletionsWithStreamingResponse: def __init__(self, completions: Completions) -> None: self._completions = completions self.create = to_streamed_response_wrapper( completions.create, ) class AsyncCompletionsWithStreamingResponse: def __init__(self, completions: AsyncCompletions) -> None: self._completions = completions self.create = async_to_streamed_response_wrapper( completions.create, ) ================================================ FILE: src/openai/resources/containers/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .files import ( Files, AsyncFiles, FilesWithRawResponse, AsyncFilesWithRawResponse, FilesWithStreamingResponse, AsyncFilesWithStreamingResponse, ) from .containers import ( Containers, AsyncContainers, ContainersWithRawResponse, AsyncContainersWithRawResponse, ContainersWithStreamingResponse, AsyncContainersWithStreamingResponse, ) __all__ = [ "Files", "AsyncFiles", "FilesWithRawResponse", "AsyncFilesWithRawResponse", "FilesWithStreamingResponse", "AsyncFilesWithStreamingResponse", "Containers", "AsyncContainers", "ContainersWithRawResponse", "AsyncContainersWithRawResponse", "ContainersWithStreamingResponse", "AsyncContainersWithStreamingResponse", ] ================================================ FILE: src/openai/resources/containers/containers.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Iterable from typing_extensions import Literal import httpx from ... import _legacy_response from ...types import container_list_params, container_create_params from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from .files.files import ( Files, AsyncFiles, FilesWithRawResponse, AsyncFilesWithRawResponse, FilesWithStreamingResponse, AsyncFilesWithStreamingResponse, ) from ...pagination import SyncCursorPage, AsyncCursorPage from ..._base_client import AsyncPaginator, make_request_options from ...types.container_list_response import ContainerListResponse from ...types.container_create_response import ContainerCreateResponse from ...types.container_retrieve_response import ContainerRetrieveResponse __all__ = ["Containers", "AsyncContainers"] class Containers(SyncAPIResource): @cached_property def files(self) -> Files: return Files(self._client) @cached_property def with_raw_response(self) -> ContainersWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return ContainersWithRawResponse(self) @cached_property def with_streaming_response(self) -> ContainersWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return ContainersWithStreamingResponse(self) def create( self, *, name: str, expires_after: container_create_params.ExpiresAfter | Omit = omit, file_ids: SequenceNotStr[str] | Omit = omit, memory_limit: Literal["1g", "4g", "16g", "64g"] | Omit = omit, network_policy: container_create_params.NetworkPolicy | Omit = omit, skills: Iterable[container_create_params.Skill] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ContainerCreateResponse: """ Create Container Args: name: Name of the container to create. expires_after: Container expiration time in seconds relative to the 'anchor' time. file_ids: IDs of files to copy to the container. memory_limit: Optional memory limit for the container. Defaults to "1g". network_policy: Network access policy for the container. skills: An optional list of skills referenced by id or inline data. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._post( "/containers", body=maybe_transform( { "name": name, "expires_after": expires_after, "file_ids": file_ids, "memory_limit": memory_limit, "network_policy": network_policy, "skills": skills, }, container_create_params.ContainerCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ContainerCreateResponse, ) def retrieve( self, container_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ContainerRetrieveResponse: """ Retrieve Container Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not container_id: raise ValueError(f"Expected a non-empty value for `container_id` but received {container_id!r}") return self._get( f"/containers/{container_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ContainerRetrieveResponse, ) def list( self, *, after: str | Omit = omit, limit: int | Omit = omit, name: str | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[ContainerListResponse]: """List Containers Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. name: Filter results by container name. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._get_api_list( "/containers", page=SyncCursorPage[ContainerListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "name": name, "order": order, }, container_list_params.ContainerListParams, ), ), model=ContainerListResponse, ) def delete( self, container_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete Container Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not container_id: raise ValueError(f"Expected a non-empty value for `container_id` but received {container_id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._delete( f"/containers/{container_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=NoneType, ) class AsyncContainers(AsyncAPIResource): @cached_property def files(self) -> AsyncFiles: return AsyncFiles(self._client) @cached_property def with_raw_response(self) -> AsyncContainersWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncContainersWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncContainersWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncContainersWithStreamingResponse(self) async def create( self, *, name: str, expires_after: container_create_params.ExpiresAfter | Omit = omit, file_ids: SequenceNotStr[str] | Omit = omit, memory_limit: Literal["1g", "4g", "16g", "64g"] | Omit = omit, network_policy: container_create_params.NetworkPolicy | Omit = omit, skills: Iterable[container_create_params.Skill] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ContainerCreateResponse: """ Create Container Args: name: Name of the container to create. expires_after: Container expiration time in seconds relative to the 'anchor' time. file_ids: IDs of files to copy to the container. memory_limit: Optional memory limit for the container. Defaults to "1g". network_policy: Network access policy for the container. skills: An optional list of skills referenced by id or inline data. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return await self._post( "/containers", body=await async_maybe_transform( { "name": name, "expires_after": expires_after, "file_ids": file_ids, "memory_limit": memory_limit, "network_policy": network_policy, "skills": skills, }, container_create_params.ContainerCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ContainerCreateResponse, ) async def retrieve( self, container_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ContainerRetrieveResponse: """ Retrieve Container Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not container_id: raise ValueError(f"Expected a non-empty value for `container_id` but received {container_id!r}") return await self._get( f"/containers/{container_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ContainerRetrieveResponse, ) def list( self, *, after: str | Omit = omit, limit: int | Omit = omit, name: str | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[ContainerListResponse, AsyncCursorPage[ContainerListResponse]]: """List Containers Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. name: Filter results by container name. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._get_api_list( "/containers", page=AsyncCursorPage[ContainerListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "name": name, "order": order, }, container_list_params.ContainerListParams, ), ), model=ContainerListResponse, ) async def delete( self, container_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete Container Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not container_id: raise ValueError(f"Expected a non-empty value for `container_id` but received {container_id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._delete( f"/containers/{container_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=NoneType, ) class ContainersWithRawResponse: def __init__(self, containers: Containers) -> None: self._containers = containers self.create = _legacy_response.to_raw_response_wrapper( containers.create, ) self.retrieve = _legacy_response.to_raw_response_wrapper( containers.retrieve, ) self.list = _legacy_response.to_raw_response_wrapper( containers.list, ) self.delete = _legacy_response.to_raw_response_wrapper( containers.delete, ) @cached_property def files(self) -> FilesWithRawResponse: return FilesWithRawResponse(self._containers.files) class AsyncContainersWithRawResponse: def __init__(self, containers: AsyncContainers) -> None: self._containers = containers self.create = _legacy_response.async_to_raw_response_wrapper( containers.create, ) self.retrieve = _legacy_response.async_to_raw_response_wrapper( containers.retrieve, ) self.list = _legacy_response.async_to_raw_response_wrapper( containers.list, ) self.delete = _legacy_response.async_to_raw_response_wrapper( containers.delete, ) @cached_property def files(self) -> AsyncFilesWithRawResponse: return AsyncFilesWithRawResponse(self._containers.files) class ContainersWithStreamingResponse: def __init__(self, containers: Containers) -> None: self._containers = containers self.create = to_streamed_response_wrapper( containers.create, ) self.retrieve = to_streamed_response_wrapper( containers.retrieve, ) self.list = to_streamed_response_wrapper( containers.list, ) self.delete = to_streamed_response_wrapper( containers.delete, ) @cached_property def files(self) -> FilesWithStreamingResponse: return FilesWithStreamingResponse(self._containers.files) class AsyncContainersWithStreamingResponse: def __init__(self, containers: AsyncContainers) -> None: self._containers = containers self.create = async_to_streamed_response_wrapper( containers.create, ) self.retrieve = async_to_streamed_response_wrapper( containers.retrieve, ) self.list = async_to_streamed_response_wrapper( containers.list, ) self.delete = async_to_streamed_response_wrapper( containers.delete, ) @cached_property def files(self) -> AsyncFilesWithStreamingResponse: return AsyncFilesWithStreamingResponse(self._containers.files) ================================================ FILE: src/openai/resources/containers/files/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .files import ( Files, AsyncFiles, FilesWithRawResponse, AsyncFilesWithRawResponse, FilesWithStreamingResponse, AsyncFilesWithStreamingResponse, ) from .content import ( Content, AsyncContent, ContentWithRawResponse, AsyncContentWithRawResponse, ContentWithStreamingResponse, AsyncContentWithStreamingResponse, ) __all__ = [ "Content", "AsyncContent", "ContentWithRawResponse", "AsyncContentWithRawResponse", "ContentWithStreamingResponse", "AsyncContentWithStreamingResponse", "Files", "AsyncFiles", "FilesWithRawResponse", "AsyncFilesWithRawResponse", "FilesWithStreamingResponse", "AsyncFilesWithStreamingResponse", ] ================================================ FILE: src/openai/resources/containers/files/content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import httpx from .... import _legacy_response from ...._types import Body, Query, Headers, NotGiven, not_given from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import ( StreamedBinaryAPIResponse, AsyncStreamedBinaryAPIResponse, to_custom_streamed_response_wrapper, async_to_custom_streamed_response_wrapper, ) from ...._base_client import make_request_options __all__ = ["Content", "AsyncContent"] class Content(SyncAPIResource): @cached_property def with_raw_response(self) -> ContentWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return ContentWithRawResponse(self) @cached_property def with_streaming_response(self) -> ContentWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return ContentWithStreamingResponse(self) def retrieve( self, file_id: str, *, container_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: """ Retrieve Container File Content Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not container_id: raise ValueError(f"Expected a non-empty value for `container_id` but received {container_id!r}") if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") extra_headers = {"Accept": "application/binary", **(extra_headers or {})} return self._get( f"/containers/{container_id}/files/{file_id}/content", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=_legacy_response.HttpxBinaryResponseContent, ) class AsyncContent(AsyncAPIResource): @cached_property def with_raw_response(self) -> AsyncContentWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncContentWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncContentWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncContentWithStreamingResponse(self) async def retrieve( self, file_id: str, *, container_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: """ Retrieve Container File Content Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not container_id: raise ValueError(f"Expected a non-empty value for `container_id` but received {container_id!r}") if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") extra_headers = {"Accept": "application/binary", **(extra_headers or {})} return await self._get( f"/containers/{container_id}/files/{file_id}/content", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=_legacy_response.HttpxBinaryResponseContent, ) class ContentWithRawResponse: def __init__(self, content: Content) -> None: self._content = content self.retrieve = _legacy_response.to_raw_response_wrapper( content.retrieve, ) class AsyncContentWithRawResponse: def __init__(self, content: AsyncContent) -> None: self._content = content self.retrieve = _legacy_response.async_to_raw_response_wrapper( content.retrieve, ) class ContentWithStreamingResponse: def __init__(self, content: Content) -> None: self._content = content self.retrieve = to_custom_streamed_response_wrapper( content.retrieve, StreamedBinaryAPIResponse, ) class AsyncContentWithStreamingResponse: def __init__(self, content: AsyncContent) -> None: self._content = content self.retrieve = async_to_custom_streamed_response_wrapper( content.retrieve, AsyncStreamedBinaryAPIResponse, ) ================================================ FILE: src/openai/resources/containers/files/files.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Mapping, cast from typing_extensions import Literal import httpx from .... import _legacy_response from .content import ( Content, AsyncContent, ContentWithRawResponse, AsyncContentWithRawResponse, ContentWithStreamingResponse, AsyncContentWithStreamingResponse, ) from ...._types import Body, Omit, Query, Headers, NoneType, NotGiven, FileTypes, omit, not_given from ...._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ....pagination import SyncCursorPage, AsyncCursorPage from ...._base_client import AsyncPaginator, make_request_options from ....types.containers import file_list_params, file_create_params from ....types.containers.file_list_response import FileListResponse from ....types.containers.file_create_response import FileCreateResponse from ....types.containers.file_retrieve_response import FileRetrieveResponse __all__ = ["Files", "AsyncFiles"] class Files(SyncAPIResource): @cached_property def content(self) -> Content: return Content(self._client) @cached_property def with_raw_response(self) -> FilesWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return FilesWithRawResponse(self) @cached_property def with_streaming_response(self) -> FilesWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return FilesWithStreamingResponse(self) def create( self, container_id: str, *, file: FileTypes | Omit = omit, file_id: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileCreateResponse: """ Create a Container File You can send either a multipart/form-data request with the raw file content, or a JSON request with a file ID. Args: file: The File object (not file name) to be uploaded. file_id: Name of the file to create. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not container_id: raise ValueError(f"Expected a non-empty value for `container_id` but received {container_id!r}") body = deepcopy_minimal( { "file": file, "file_id": file_id, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) if files: # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return self._post( f"/containers/{container_id}/files", body=maybe_transform(body, file_create_params.FileCreateParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FileCreateResponse, ) def retrieve( self, file_id: str, *, container_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileRetrieveResponse: """ Retrieve Container File Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not container_id: raise ValueError(f"Expected a non-empty value for `container_id` but received {container_id!r}") if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return self._get( f"/containers/{container_id}/files/{file_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FileRetrieveResponse, ) def list( self, container_id: str, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[FileListResponse]: """List Container files Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not container_id: raise ValueError(f"Expected a non-empty value for `container_id` but received {container_id!r}") return self._get_api_list( f"/containers/{container_id}/files", page=SyncCursorPage[FileListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, }, file_list_params.FileListParams, ), ), model=FileListResponse, ) def delete( self, file_id: str, *, container_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete Container File Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not container_id: raise ValueError(f"Expected a non-empty value for `container_id` but received {container_id!r}") if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._delete( f"/containers/{container_id}/files/{file_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=NoneType, ) class AsyncFiles(AsyncAPIResource): @cached_property def content(self) -> AsyncContent: return AsyncContent(self._client) @cached_property def with_raw_response(self) -> AsyncFilesWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncFilesWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncFilesWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncFilesWithStreamingResponse(self) async def create( self, container_id: str, *, file: FileTypes | Omit = omit, file_id: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileCreateResponse: """ Create a Container File You can send either a multipart/form-data request with the raw file content, or a JSON request with a file ID. Args: file: The File object (not file name) to be uploaded. file_id: Name of the file to create. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not container_id: raise ValueError(f"Expected a non-empty value for `container_id` but received {container_id!r}") body = deepcopy_minimal( { "file": file, "file_id": file_id, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) if files: # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return await self._post( f"/containers/{container_id}/files", body=await async_maybe_transform(body, file_create_params.FileCreateParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FileCreateResponse, ) async def retrieve( self, file_id: str, *, container_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileRetrieveResponse: """ Retrieve Container File Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not container_id: raise ValueError(f"Expected a non-empty value for `container_id` but received {container_id!r}") if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return await self._get( f"/containers/{container_id}/files/{file_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FileRetrieveResponse, ) def list( self, container_id: str, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[FileListResponse, AsyncCursorPage[FileListResponse]]: """List Container files Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not container_id: raise ValueError(f"Expected a non-empty value for `container_id` but received {container_id!r}") return self._get_api_list( f"/containers/{container_id}/files", page=AsyncCursorPage[FileListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, }, file_list_params.FileListParams, ), ), model=FileListResponse, ) async def delete( self, file_id: str, *, container_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete Container File Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not container_id: raise ValueError(f"Expected a non-empty value for `container_id` but received {container_id!r}") if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._delete( f"/containers/{container_id}/files/{file_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=NoneType, ) class FilesWithRawResponse: def __init__(self, files: Files) -> None: self._files = files self.create = _legacy_response.to_raw_response_wrapper( files.create, ) self.retrieve = _legacy_response.to_raw_response_wrapper( files.retrieve, ) self.list = _legacy_response.to_raw_response_wrapper( files.list, ) self.delete = _legacy_response.to_raw_response_wrapper( files.delete, ) @cached_property def content(self) -> ContentWithRawResponse: return ContentWithRawResponse(self._files.content) class AsyncFilesWithRawResponse: def __init__(self, files: AsyncFiles) -> None: self._files = files self.create = _legacy_response.async_to_raw_response_wrapper( files.create, ) self.retrieve = _legacy_response.async_to_raw_response_wrapper( files.retrieve, ) self.list = _legacy_response.async_to_raw_response_wrapper( files.list, ) self.delete = _legacy_response.async_to_raw_response_wrapper( files.delete, ) @cached_property def content(self) -> AsyncContentWithRawResponse: return AsyncContentWithRawResponse(self._files.content) class FilesWithStreamingResponse: def __init__(self, files: Files) -> None: self._files = files self.create = to_streamed_response_wrapper( files.create, ) self.retrieve = to_streamed_response_wrapper( files.retrieve, ) self.list = to_streamed_response_wrapper( files.list, ) self.delete = to_streamed_response_wrapper( files.delete, ) @cached_property def content(self) -> ContentWithStreamingResponse: return ContentWithStreamingResponse(self._files.content) class AsyncFilesWithStreamingResponse: def __init__(self, files: AsyncFiles) -> None: self._files = files self.create = async_to_streamed_response_wrapper( files.create, ) self.retrieve = async_to_streamed_response_wrapper( files.retrieve, ) self.list = async_to_streamed_response_wrapper( files.list, ) self.delete = async_to_streamed_response_wrapper( files.delete, ) @cached_property def content(self) -> AsyncContentWithStreamingResponse: return AsyncContentWithStreamingResponse(self._files.content) ================================================ FILE: src/openai/resources/conversations/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .items import ( Items, AsyncItems, ItemsWithRawResponse, AsyncItemsWithRawResponse, ItemsWithStreamingResponse, AsyncItemsWithStreamingResponse, ) from .conversations import ( Conversations, AsyncConversations, ConversationsWithRawResponse, AsyncConversationsWithRawResponse, ConversationsWithStreamingResponse, AsyncConversationsWithStreamingResponse, ) __all__ = [ "Items", "AsyncItems", "ItemsWithRawResponse", "AsyncItemsWithRawResponse", "ItemsWithStreamingResponse", "AsyncItemsWithStreamingResponse", "Conversations", "AsyncConversations", "ConversationsWithRawResponse", "AsyncConversationsWithRawResponse", "ConversationsWithStreamingResponse", "AsyncConversationsWithStreamingResponse", ] ================================================ FILE: src/openai/resources/conversations/api.md ================================================ # Conversations Types: ```python from openai.types.conversations import ( ComputerScreenshotContent, Conversation, ConversationDeleted, ConversationDeletedResource, Message, SummaryTextContent, TextContent, InputTextContent, OutputTextContent, RefusalContent, InputImageContent, InputFileContent, ) ``` Methods: - client.conversations.create(\*\*params) -> Conversation - client.conversations.retrieve(conversation_id) -> Conversation - client.conversations.update(conversation_id, \*\*params) -> Conversation - client.conversations.delete(conversation_id) -> ConversationDeletedResource ## Items Types: ```python from openai.types.conversations import ConversationItem, ConversationItemList ``` Methods: - client.conversations.items.create(conversation_id, \*\*params) -> ConversationItemList - client.conversations.items.retrieve(item_id, \*, conversation_id, \*\*params) -> ConversationItem - client.conversations.items.list(conversation_id, \*\*params) -> SyncConversationCursorPage[ConversationItem] - client.conversations.items.delete(item_id, \*, conversation_id) -> Conversation ================================================ FILE: src/openai/resources/conversations/conversations.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Iterable, Optional import httpx from ... import _legacy_response from .items import ( Items, AsyncItems, ItemsWithRawResponse, AsyncItemsWithRawResponse, ItemsWithStreamingResponse, AsyncItemsWithStreamingResponse, ) from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ..._base_client import make_request_options from ...types.conversations import conversation_create_params, conversation_update_params from ...types.shared_params.metadata import Metadata from ...types.conversations.conversation import Conversation from ...types.responses.response_input_item_param import ResponseInputItemParam from ...types.conversations.conversation_deleted_resource import ConversationDeletedResource __all__ = ["Conversations", "AsyncConversations"] class Conversations(SyncAPIResource): """Manage conversations and conversation items.""" @cached_property def items(self) -> Items: """Manage conversations and conversation items.""" return Items(self._client) @cached_property def with_raw_response(self) -> ConversationsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return ConversationsWithRawResponse(self) @cached_property def with_streaming_response(self) -> ConversationsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return ConversationsWithStreamingResponse(self) def create( self, *, items: Optional[Iterable[ResponseInputItemParam]] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Conversation: """ Create a conversation. Args: items: Initial items to include in the conversation context. You may add up to 20 items at a time. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._post( "/conversations", body=maybe_transform( { "items": items, "metadata": metadata, }, conversation_create_params.ConversationCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Conversation, ) def retrieve( self, conversation_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Conversation: """ Get a conversation Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not conversation_id: raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") return self._get( f"/conversations/{conversation_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Conversation, ) def update( self, conversation_id: str, *, metadata: Optional[Metadata], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Conversation: """ Update a conversation Args: metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not conversation_id: raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") return self._post( f"/conversations/{conversation_id}", body=maybe_transform({"metadata": metadata}, conversation_update_params.ConversationUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Conversation, ) def delete( self, conversation_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ConversationDeletedResource: """Delete a conversation. Items in the conversation will not be deleted. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not conversation_id: raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") return self._delete( f"/conversations/{conversation_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ConversationDeletedResource, ) class AsyncConversations(AsyncAPIResource): """Manage conversations and conversation items.""" @cached_property def items(self) -> AsyncItems: """Manage conversations and conversation items.""" return AsyncItems(self._client) @cached_property def with_raw_response(self) -> AsyncConversationsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncConversationsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncConversationsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncConversationsWithStreamingResponse(self) async def create( self, *, items: Optional[Iterable[ResponseInputItemParam]] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Conversation: """ Create a conversation. Args: items: Initial items to include in the conversation context. You may add up to 20 items at a time. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return await self._post( "/conversations", body=await async_maybe_transform( { "items": items, "metadata": metadata, }, conversation_create_params.ConversationCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Conversation, ) async def retrieve( self, conversation_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Conversation: """ Get a conversation Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not conversation_id: raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") return await self._get( f"/conversations/{conversation_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Conversation, ) async def update( self, conversation_id: str, *, metadata: Optional[Metadata], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Conversation: """ Update a conversation Args: metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not conversation_id: raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") return await self._post( f"/conversations/{conversation_id}", body=await async_maybe_transform( {"metadata": metadata}, conversation_update_params.ConversationUpdateParams ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Conversation, ) async def delete( self, conversation_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ConversationDeletedResource: """Delete a conversation. Items in the conversation will not be deleted. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not conversation_id: raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") return await self._delete( f"/conversations/{conversation_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ConversationDeletedResource, ) class ConversationsWithRawResponse: def __init__(self, conversations: Conversations) -> None: self._conversations = conversations self.create = _legacy_response.to_raw_response_wrapper( conversations.create, ) self.retrieve = _legacy_response.to_raw_response_wrapper( conversations.retrieve, ) self.update = _legacy_response.to_raw_response_wrapper( conversations.update, ) self.delete = _legacy_response.to_raw_response_wrapper( conversations.delete, ) @cached_property def items(self) -> ItemsWithRawResponse: """Manage conversations and conversation items.""" return ItemsWithRawResponse(self._conversations.items) class AsyncConversationsWithRawResponse: def __init__(self, conversations: AsyncConversations) -> None: self._conversations = conversations self.create = _legacy_response.async_to_raw_response_wrapper( conversations.create, ) self.retrieve = _legacy_response.async_to_raw_response_wrapper( conversations.retrieve, ) self.update = _legacy_response.async_to_raw_response_wrapper( conversations.update, ) self.delete = _legacy_response.async_to_raw_response_wrapper( conversations.delete, ) @cached_property def items(self) -> AsyncItemsWithRawResponse: """Manage conversations and conversation items.""" return AsyncItemsWithRawResponse(self._conversations.items) class ConversationsWithStreamingResponse: def __init__(self, conversations: Conversations) -> None: self._conversations = conversations self.create = to_streamed_response_wrapper( conversations.create, ) self.retrieve = to_streamed_response_wrapper( conversations.retrieve, ) self.update = to_streamed_response_wrapper( conversations.update, ) self.delete = to_streamed_response_wrapper( conversations.delete, ) @cached_property def items(self) -> ItemsWithStreamingResponse: """Manage conversations and conversation items.""" return ItemsWithStreamingResponse(self._conversations.items) class AsyncConversationsWithStreamingResponse: def __init__(self, conversations: AsyncConversations) -> None: self._conversations = conversations self.create = async_to_streamed_response_wrapper( conversations.create, ) self.retrieve = async_to_streamed_response_wrapper( conversations.retrieve, ) self.update = async_to_streamed_response_wrapper( conversations.update, ) self.delete = async_to_streamed_response_wrapper( conversations.delete, ) @cached_property def items(self) -> AsyncItemsWithStreamingResponse: """Manage conversations and conversation items.""" return AsyncItemsWithStreamingResponse(self._conversations.items) ================================================ FILE: src/openai/resources/conversations/items.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Any, List, Iterable, cast from typing_extensions import Literal import httpx from ... import _legacy_response from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ...pagination import SyncConversationCursorPage, AsyncConversationCursorPage from ..._base_client import AsyncPaginator, make_request_options from ...types.conversations import item_list_params, item_create_params, item_retrieve_params from ...types.conversations.conversation import Conversation from ...types.responses.response_includable import ResponseIncludable from ...types.conversations.conversation_item import ConversationItem from ...types.responses.response_input_item_param import ResponseInputItemParam from ...types.conversations.conversation_item_list import ConversationItemList __all__ = ["Items", "AsyncItems"] class Items(SyncAPIResource): """Manage conversations and conversation items.""" @cached_property def with_raw_response(self) -> ItemsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return ItemsWithRawResponse(self) @cached_property def with_streaming_response(self) -> ItemsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return ItemsWithStreamingResponse(self) def create( self, conversation_id: str, *, items: Iterable[ResponseInputItemParam], include: List[ResponseIncludable] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ConversationItemList: """ Create items in a conversation with the given ID. Args: items: The items to add to the conversation. You may add up to 20 items at a time. include: Additional fields to include in the response. See the `include` parameter for [listing Conversation items above](https://platform.openai.com/docs/api-reference/conversations/list-items#conversations_list_items-include) for more information. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not conversation_id: raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") return self._post( f"/conversations/{conversation_id}/items", body=maybe_transform({"items": items}, item_create_params.ItemCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform({"include": include}, item_create_params.ItemCreateParams), ), cast_to=ConversationItemList, ) def retrieve( self, item_id: str, *, conversation_id: str, include: List[ResponseIncludable] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ConversationItem: """ Get a single item from a conversation with the given IDs. Args: include: Additional fields to include in the response. See the `include` parameter for [listing Conversation items above](https://platform.openai.com/docs/api-reference/conversations/list-items#conversations_list_items-include) for more information. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not conversation_id: raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") if not item_id: raise ValueError(f"Expected a non-empty value for `item_id` but received {item_id!r}") return cast( ConversationItem, self._get( f"/conversations/{conversation_id}/items/{item_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform({"include": include}, item_retrieve_params.ItemRetrieveParams), ), cast_to=cast(Any, ConversationItem), # Union types cannot be passed in as arguments in the type system ), ) def list( self, conversation_id: str, *, after: str | Omit = omit, include: List[ResponseIncludable] | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncConversationCursorPage[ConversationItem]: """ List all items for a conversation with the given ID. Args: after: An item ID to list items after, used in pagination. include: Specify additional output data to include in the model response. Currently supported values are: - `web_search_call.action.sources`: Include the sources of the web search tool call. - `code_interpreter_call.outputs`: Includes the outputs of python code execution in code interpreter tool call items. - `computer_call_output.output.image_url`: Include image urls from the computer call output. - `file_search_call.results`: Include the search results of the file search tool call. - `message.input_image.image_url`: Include image urls from the input message. - `message.output_text.logprobs`: Include logprobs with assistant messages. - `reasoning.encrypted_content`: Includes an encrypted version of reasoning tokens in reasoning item outputs. This enables reasoning items to be used in multi-turn conversations when using the Responses API statelessly (like when the `store` parameter is set to `false`, or when an organization is enrolled in the zero data retention program). limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: The order to return the input items in. Default is `desc`. - `asc`: Return the input items in ascending order. - `desc`: Return the input items in descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not conversation_id: raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") return self._get_api_list( f"/conversations/{conversation_id}/items", page=SyncConversationCursorPage[ConversationItem], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "include": include, "limit": limit, "order": order, }, item_list_params.ItemListParams, ), ), model=cast(Any, ConversationItem), # Union types cannot be passed in as arguments in the type system ) def delete( self, item_id: str, *, conversation_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Conversation: """ Delete an item from a conversation with the given IDs. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not conversation_id: raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") if not item_id: raise ValueError(f"Expected a non-empty value for `item_id` but received {item_id!r}") return self._delete( f"/conversations/{conversation_id}/items/{item_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Conversation, ) class AsyncItems(AsyncAPIResource): """Manage conversations and conversation items.""" @cached_property def with_raw_response(self) -> AsyncItemsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncItemsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncItemsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncItemsWithStreamingResponse(self) async def create( self, conversation_id: str, *, items: Iterable[ResponseInputItemParam], include: List[ResponseIncludable] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ConversationItemList: """ Create items in a conversation with the given ID. Args: items: The items to add to the conversation. You may add up to 20 items at a time. include: Additional fields to include in the response. See the `include` parameter for [listing Conversation items above](https://platform.openai.com/docs/api-reference/conversations/list-items#conversations_list_items-include) for more information. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not conversation_id: raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") return await self._post( f"/conversations/{conversation_id}/items", body=await async_maybe_transform({"items": items}, item_create_params.ItemCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=await async_maybe_transform({"include": include}, item_create_params.ItemCreateParams), ), cast_to=ConversationItemList, ) async def retrieve( self, item_id: str, *, conversation_id: str, include: List[ResponseIncludable] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ConversationItem: """ Get a single item from a conversation with the given IDs. Args: include: Additional fields to include in the response. See the `include` parameter for [listing Conversation items above](https://platform.openai.com/docs/api-reference/conversations/list-items#conversations_list_items-include) for more information. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not conversation_id: raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") if not item_id: raise ValueError(f"Expected a non-empty value for `item_id` but received {item_id!r}") return cast( ConversationItem, await self._get( f"/conversations/{conversation_id}/items/{item_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=await async_maybe_transform({"include": include}, item_retrieve_params.ItemRetrieveParams), ), cast_to=cast(Any, ConversationItem), # Union types cannot be passed in as arguments in the type system ), ) def list( self, conversation_id: str, *, after: str | Omit = omit, include: List[ResponseIncludable] | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[ConversationItem, AsyncConversationCursorPage[ConversationItem]]: """ List all items for a conversation with the given ID. Args: after: An item ID to list items after, used in pagination. include: Specify additional output data to include in the model response. Currently supported values are: - `web_search_call.action.sources`: Include the sources of the web search tool call. - `code_interpreter_call.outputs`: Includes the outputs of python code execution in code interpreter tool call items. - `computer_call_output.output.image_url`: Include image urls from the computer call output. - `file_search_call.results`: Include the search results of the file search tool call. - `message.input_image.image_url`: Include image urls from the input message. - `message.output_text.logprobs`: Include logprobs with assistant messages. - `reasoning.encrypted_content`: Includes an encrypted version of reasoning tokens in reasoning item outputs. This enables reasoning items to be used in multi-turn conversations when using the Responses API statelessly (like when the `store` parameter is set to `false`, or when an organization is enrolled in the zero data retention program). limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: The order to return the input items in. Default is `desc`. - `asc`: Return the input items in ascending order. - `desc`: Return the input items in descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not conversation_id: raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") return self._get_api_list( f"/conversations/{conversation_id}/items", page=AsyncConversationCursorPage[ConversationItem], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "include": include, "limit": limit, "order": order, }, item_list_params.ItemListParams, ), ), model=cast(Any, ConversationItem), # Union types cannot be passed in as arguments in the type system ) async def delete( self, item_id: str, *, conversation_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Conversation: """ Delete an item from a conversation with the given IDs. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not conversation_id: raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") if not item_id: raise ValueError(f"Expected a non-empty value for `item_id` but received {item_id!r}") return await self._delete( f"/conversations/{conversation_id}/items/{item_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Conversation, ) class ItemsWithRawResponse: def __init__(self, items: Items) -> None: self._items = items self.create = _legacy_response.to_raw_response_wrapper( items.create, ) self.retrieve = _legacy_response.to_raw_response_wrapper( items.retrieve, ) self.list = _legacy_response.to_raw_response_wrapper( items.list, ) self.delete = _legacy_response.to_raw_response_wrapper( items.delete, ) class AsyncItemsWithRawResponse: def __init__(self, items: AsyncItems) -> None: self._items = items self.create = _legacy_response.async_to_raw_response_wrapper( items.create, ) self.retrieve = _legacy_response.async_to_raw_response_wrapper( items.retrieve, ) self.list = _legacy_response.async_to_raw_response_wrapper( items.list, ) self.delete = _legacy_response.async_to_raw_response_wrapper( items.delete, ) class ItemsWithStreamingResponse: def __init__(self, items: Items) -> None: self._items = items self.create = to_streamed_response_wrapper( items.create, ) self.retrieve = to_streamed_response_wrapper( items.retrieve, ) self.list = to_streamed_response_wrapper( items.list, ) self.delete = to_streamed_response_wrapper( items.delete, ) class AsyncItemsWithStreamingResponse: def __init__(self, items: AsyncItems) -> None: self._items = items self.create = async_to_streamed_response_wrapper( items.create, ) self.retrieve = async_to_streamed_response_wrapper( items.retrieve, ) self.list = async_to_streamed_response_wrapper( items.list, ) self.delete = async_to_streamed_response_wrapper( items.delete, ) ================================================ FILE: src/openai/resources/embeddings.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import array import base64 from typing import Union, Iterable, cast from typing_extensions import Literal import httpx from .. import _legacy_response from ..types import embedding_create_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from .._utils import is_given, maybe_transform from .._compat import cached_property from .._extras import numpy as np, has_numpy from .._resource import SyncAPIResource, AsyncAPIResource from .._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from .._base_client import make_request_options from ..types.embedding_model import EmbeddingModel from ..types.create_embedding_response import CreateEmbeddingResponse __all__ = ["Embeddings", "AsyncEmbeddings"] class Embeddings(SyncAPIResource): """ Get a vector representation of a given input that can be easily consumed by machine learning models and algorithms. """ @cached_property def with_raw_response(self) -> EmbeddingsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return EmbeddingsWithRawResponse(self) @cached_property def with_streaming_response(self) -> EmbeddingsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return EmbeddingsWithStreamingResponse(self) def create( self, *, input: Union[str, SequenceNotStr[str], Iterable[int], Iterable[Iterable[int]]], model: Union[str, EmbeddingModel], dimensions: int | Omit = omit, encoding_format: Literal["float", "base64"] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CreateEmbeddingResponse: """ Creates an embedding vector representing the input text. Args: input: Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a single request, pass an array of strings or array of token arrays. The input must not exceed the max input tokens for the model (8192 tokens for all embedding models), cannot be an empty string, and any array must be 2048 dimensions or less. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens. In addition to the per-input token limit, all embedding models enforce a maximum of 300,000 tokens summed across all inputs in a single request. model: ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models) for descriptions of them. dimensions: The number of dimensions the resulting output embeddings should have. Only supported in `text-embedding-3` and later models. encoding_format: The format to return the embeddings in. Can be either `float` or [`base64`](https://pypi.org/project/pybase64/). user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ params = { "input": input, "model": model, "user": user, "dimensions": dimensions, "encoding_format": encoding_format, } if not is_given(encoding_format): params["encoding_format"] = "base64" def parser(obj: CreateEmbeddingResponse) -> CreateEmbeddingResponse: if is_given(encoding_format): # don't modify the response object if a user explicitly asked for a format return obj if not obj.data: raise ValueError("No embedding data received") for embedding in obj.data: data = cast(object, embedding.embedding) if not isinstance(data, str): continue if not has_numpy(): # use array for base64 optimisation embedding.embedding = array.array("f", base64.b64decode(data)).tolist() else: embedding.embedding = np.frombuffer( # type: ignore[no-untyped-call] base64.b64decode(data), dtype="float32" ).tolist() return obj return self._post( "/embeddings", body=maybe_transform(params, embedding_create_params.EmbeddingCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, post_parser=parser, ), cast_to=CreateEmbeddingResponse, ) class AsyncEmbeddings(AsyncAPIResource): """ Get a vector representation of a given input that can be easily consumed by machine learning models and algorithms. """ @cached_property def with_raw_response(self) -> AsyncEmbeddingsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncEmbeddingsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncEmbeddingsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncEmbeddingsWithStreamingResponse(self) async def create( self, *, input: Union[str, SequenceNotStr[str], Iterable[int], Iterable[Iterable[int]]], model: Union[str, EmbeddingModel], dimensions: int | Omit = omit, encoding_format: Literal["float", "base64"] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CreateEmbeddingResponse: """ Creates an embedding vector representing the input text. Args: input: Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a single request, pass an array of strings or array of token arrays. The input must not exceed the max input tokens for the model (8192 tokens for all embedding models), cannot be an empty string, and any array must be 2048 dimensions or less. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens. In addition to the per-input token limit, all embedding models enforce a maximum of 300,000 tokens summed across all inputs in a single request. model: ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models) for descriptions of them. dimensions: The number of dimensions the resulting output embeddings should have. Only supported in `text-embedding-3` and later models. encoding_format: The format to return the embeddings in. Can be either `float` or [`base64`](https://pypi.org/project/pybase64/). user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ params = { "input": input, "model": model, "user": user, "dimensions": dimensions, "encoding_format": encoding_format, } if not is_given(encoding_format): params["encoding_format"] = "base64" def parser(obj: CreateEmbeddingResponse) -> CreateEmbeddingResponse: if is_given(encoding_format): # don't modify the response object if a user explicitly asked for a format return obj if not obj.data: raise ValueError("No embedding data received") for embedding in obj.data: data = cast(object, embedding.embedding) if not isinstance(data, str): continue if not has_numpy(): # use array for base64 optimisation embedding.embedding = array.array("f", base64.b64decode(data)).tolist() else: embedding.embedding = np.frombuffer( # type: ignore[no-untyped-call] base64.b64decode(data), dtype="float32" ).tolist() return obj return await self._post( "/embeddings", body=maybe_transform(params, embedding_create_params.EmbeddingCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, post_parser=parser, ), cast_to=CreateEmbeddingResponse, ) class EmbeddingsWithRawResponse: def __init__(self, embeddings: Embeddings) -> None: self._embeddings = embeddings self.create = _legacy_response.to_raw_response_wrapper( embeddings.create, ) class AsyncEmbeddingsWithRawResponse: def __init__(self, embeddings: AsyncEmbeddings) -> None: self._embeddings = embeddings self.create = _legacy_response.async_to_raw_response_wrapper( embeddings.create, ) class EmbeddingsWithStreamingResponse: def __init__(self, embeddings: Embeddings) -> None: self._embeddings = embeddings self.create = to_streamed_response_wrapper( embeddings.create, ) class AsyncEmbeddingsWithStreamingResponse: def __init__(self, embeddings: AsyncEmbeddings) -> None: self._embeddings = embeddings self.create = async_to_streamed_response_wrapper( embeddings.create, ) ================================================ FILE: src/openai/resources/evals/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .runs import ( Runs, AsyncRuns, RunsWithRawResponse, AsyncRunsWithRawResponse, RunsWithStreamingResponse, AsyncRunsWithStreamingResponse, ) from .evals import ( Evals, AsyncEvals, EvalsWithRawResponse, AsyncEvalsWithRawResponse, EvalsWithStreamingResponse, AsyncEvalsWithStreamingResponse, ) __all__ = [ "Runs", "AsyncRuns", "RunsWithRawResponse", "AsyncRunsWithRawResponse", "RunsWithStreamingResponse", "AsyncRunsWithStreamingResponse", "Evals", "AsyncEvals", "EvalsWithRawResponse", "AsyncEvalsWithRawResponse", "EvalsWithStreamingResponse", "AsyncEvalsWithStreamingResponse", ] ================================================ FILE: src/openai/resources/evals/evals.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Iterable, Optional from typing_extensions import Literal import httpx from ... import _legacy_response from ...types import eval_list_params, eval_create_params, eval_update_params from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from .runs.runs import ( Runs, AsyncRuns, RunsWithRawResponse, AsyncRunsWithRawResponse, RunsWithStreamingResponse, AsyncRunsWithStreamingResponse, ) from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ...pagination import SyncCursorPage, AsyncCursorPage from ..._base_client import AsyncPaginator, make_request_options from ...types.eval_list_response import EvalListResponse from ...types.eval_create_response import EvalCreateResponse from ...types.eval_delete_response import EvalDeleteResponse from ...types.eval_update_response import EvalUpdateResponse from ...types.eval_retrieve_response import EvalRetrieveResponse from ...types.shared_params.metadata import Metadata __all__ = ["Evals", "AsyncEvals"] class Evals(SyncAPIResource): """Manage and run evals in the OpenAI platform.""" @cached_property def runs(self) -> Runs: """Manage and run evals in the OpenAI platform.""" return Runs(self._client) @cached_property def with_raw_response(self) -> EvalsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return EvalsWithRawResponse(self) @cached_property def with_streaming_response(self) -> EvalsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return EvalsWithStreamingResponse(self) def create( self, *, data_source_config: eval_create_params.DataSourceConfig, testing_criteria: Iterable[eval_create_params.TestingCriterion], metadata: Optional[Metadata] | Omit = omit, name: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EvalCreateResponse: """ Create the structure of an evaluation that can be used to test a model's performance. An evaluation is a set of testing criteria and the config for a data source, which dictates the schema of the data used in the evaluation. After creating an evaluation, you can run it on different models and model parameters. We support several types of graders and datasources. For more information, see the [Evals guide](https://platform.openai.com/docs/guides/evals). Args: data_source_config: The configuration for the data source used for the evaluation runs. Dictates the schema of the data used in the evaluation. testing_criteria: A list of graders for all eval runs in this group. Graders can reference variables in the data source using double curly braces notation, like `{{item.variable_name}}`. To reference the model's output, use the `sample` namespace (ie, `{{sample.output_text}}`). metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. name: The name of the evaluation. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._post( "/evals", body=maybe_transform( { "data_source_config": data_source_config, "testing_criteria": testing_criteria, "metadata": metadata, "name": name, }, eval_create_params.EvalCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=EvalCreateResponse, ) def retrieve( self, eval_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EvalRetrieveResponse: """ Get an evaluation by ID. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") return self._get( f"/evals/{eval_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=EvalRetrieveResponse, ) def update( self, eval_id: str, *, metadata: Optional[Metadata] | Omit = omit, name: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EvalUpdateResponse: """ Update certain properties of an evaluation. Args: metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. name: Rename the evaluation. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") return self._post( f"/evals/{eval_id}", body=maybe_transform( { "metadata": metadata, "name": name, }, eval_update_params.EvalUpdateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=EvalUpdateResponse, ) def list( self, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, order_by: Literal["created_at", "updated_at"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[EvalListResponse]: """ List evaluations for a project. Args: after: Identifier for the last eval from the previous pagination request. limit: Number of evals to retrieve. order: Sort order for evals by timestamp. Use `asc` for ascending order or `desc` for descending order. order_by: Evals can be ordered by creation time or last updated time. Use `created_at` for creation time or `updated_at` for last updated time. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._get_api_list( "/evals", page=SyncCursorPage[EvalListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, "order_by": order_by, }, eval_list_params.EvalListParams, ), ), model=EvalListResponse, ) def delete( self, eval_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EvalDeleteResponse: """ Delete an evaluation. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") return self._delete( f"/evals/{eval_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=EvalDeleteResponse, ) class AsyncEvals(AsyncAPIResource): """Manage and run evals in the OpenAI platform.""" @cached_property def runs(self) -> AsyncRuns: """Manage and run evals in the OpenAI platform.""" return AsyncRuns(self._client) @cached_property def with_raw_response(self) -> AsyncEvalsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncEvalsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncEvalsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncEvalsWithStreamingResponse(self) async def create( self, *, data_source_config: eval_create_params.DataSourceConfig, testing_criteria: Iterable[eval_create_params.TestingCriterion], metadata: Optional[Metadata] | Omit = omit, name: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EvalCreateResponse: """ Create the structure of an evaluation that can be used to test a model's performance. An evaluation is a set of testing criteria and the config for a data source, which dictates the schema of the data used in the evaluation. After creating an evaluation, you can run it on different models and model parameters. We support several types of graders and datasources. For more information, see the [Evals guide](https://platform.openai.com/docs/guides/evals). Args: data_source_config: The configuration for the data source used for the evaluation runs. Dictates the schema of the data used in the evaluation. testing_criteria: A list of graders for all eval runs in this group. Graders can reference variables in the data source using double curly braces notation, like `{{item.variable_name}}`. To reference the model's output, use the `sample` namespace (ie, `{{sample.output_text}}`). metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. name: The name of the evaluation. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return await self._post( "/evals", body=await async_maybe_transform( { "data_source_config": data_source_config, "testing_criteria": testing_criteria, "metadata": metadata, "name": name, }, eval_create_params.EvalCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=EvalCreateResponse, ) async def retrieve( self, eval_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EvalRetrieveResponse: """ Get an evaluation by ID. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") return await self._get( f"/evals/{eval_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=EvalRetrieveResponse, ) async def update( self, eval_id: str, *, metadata: Optional[Metadata] | Omit = omit, name: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EvalUpdateResponse: """ Update certain properties of an evaluation. Args: metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. name: Rename the evaluation. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") return await self._post( f"/evals/{eval_id}", body=await async_maybe_transform( { "metadata": metadata, "name": name, }, eval_update_params.EvalUpdateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=EvalUpdateResponse, ) def list( self, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, order_by: Literal["created_at", "updated_at"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[EvalListResponse, AsyncCursorPage[EvalListResponse]]: """ List evaluations for a project. Args: after: Identifier for the last eval from the previous pagination request. limit: Number of evals to retrieve. order: Sort order for evals by timestamp. Use `asc` for ascending order or `desc` for descending order. order_by: Evals can be ordered by creation time or last updated time. Use `created_at` for creation time or `updated_at` for last updated time. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._get_api_list( "/evals", page=AsyncCursorPage[EvalListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, "order_by": order_by, }, eval_list_params.EvalListParams, ), ), model=EvalListResponse, ) async def delete( self, eval_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EvalDeleteResponse: """ Delete an evaluation. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") return await self._delete( f"/evals/{eval_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=EvalDeleteResponse, ) class EvalsWithRawResponse: def __init__(self, evals: Evals) -> None: self._evals = evals self.create = _legacy_response.to_raw_response_wrapper( evals.create, ) self.retrieve = _legacy_response.to_raw_response_wrapper( evals.retrieve, ) self.update = _legacy_response.to_raw_response_wrapper( evals.update, ) self.list = _legacy_response.to_raw_response_wrapper( evals.list, ) self.delete = _legacy_response.to_raw_response_wrapper( evals.delete, ) @cached_property def runs(self) -> RunsWithRawResponse: """Manage and run evals in the OpenAI platform.""" return RunsWithRawResponse(self._evals.runs) class AsyncEvalsWithRawResponse: def __init__(self, evals: AsyncEvals) -> None: self._evals = evals self.create = _legacy_response.async_to_raw_response_wrapper( evals.create, ) self.retrieve = _legacy_response.async_to_raw_response_wrapper( evals.retrieve, ) self.update = _legacy_response.async_to_raw_response_wrapper( evals.update, ) self.list = _legacy_response.async_to_raw_response_wrapper( evals.list, ) self.delete = _legacy_response.async_to_raw_response_wrapper( evals.delete, ) @cached_property def runs(self) -> AsyncRunsWithRawResponse: """Manage and run evals in the OpenAI platform.""" return AsyncRunsWithRawResponse(self._evals.runs) class EvalsWithStreamingResponse: def __init__(self, evals: Evals) -> None: self._evals = evals self.create = to_streamed_response_wrapper( evals.create, ) self.retrieve = to_streamed_response_wrapper( evals.retrieve, ) self.update = to_streamed_response_wrapper( evals.update, ) self.list = to_streamed_response_wrapper( evals.list, ) self.delete = to_streamed_response_wrapper( evals.delete, ) @cached_property def runs(self) -> RunsWithStreamingResponse: """Manage and run evals in the OpenAI platform.""" return RunsWithStreamingResponse(self._evals.runs) class AsyncEvalsWithStreamingResponse: def __init__(self, evals: AsyncEvals) -> None: self._evals = evals self.create = async_to_streamed_response_wrapper( evals.create, ) self.retrieve = async_to_streamed_response_wrapper( evals.retrieve, ) self.update = async_to_streamed_response_wrapper( evals.update, ) self.list = async_to_streamed_response_wrapper( evals.list, ) self.delete = async_to_streamed_response_wrapper( evals.delete, ) @cached_property def runs(self) -> AsyncRunsWithStreamingResponse: """Manage and run evals in the OpenAI platform.""" return AsyncRunsWithStreamingResponse(self._evals.runs) ================================================ FILE: src/openai/resources/evals/runs/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .runs import ( Runs, AsyncRuns, RunsWithRawResponse, AsyncRunsWithRawResponse, RunsWithStreamingResponse, AsyncRunsWithStreamingResponse, ) from .output_items import ( OutputItems, AsyncOutputItems, OutputItemsWithRawResponse, AsyncOutputItemsWithRawResponse, OutputItemsWithStreamingResponse, AsyncOutputItemsWithStreamingResponse, ) __all__ = [ "OutputItems", "AsyncOutputItems", "OutputItemsWithRawResponse", "AsyncOutputItemsWithRawResponse", "OutputItemsWithStreamingResponse", "AsyncOutputItemsWithStreamingResponse", "Runs", "AsyncRuns", "RunsWithRawResponse", "AsyncRunsWithRawResponse", "RunsWithStreamingResponse", "AsyncRunsWithStreamingResponse", ] ================================================ FILE: src/openai/resources/evals/runs/output_items.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal import httpx from .... import _legacy_response from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ...._utils import maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ....pagination import SyncCursorPage, AsyncCursorPage from ...._base_client import AsyncPaginator, make_request_options from ....types.evals.runs import output_item_list_params from ....types.evals.runs.output_item_list_response import OutputItemListResponse from ....types.evals.runs.output_item_retrieve_response import OutputItemRetrieveResponse __all__ = ["OutputItems", "AsyncOutputItems"] class OutputItems(SyncAPIResource): """Manage and run evals in the OpenAI platform.""" @cached_property def with_raw_response(self) -> OutputItemsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return OutputItemsWithRawResponse(self) @cached_property def with_streaming_response(self) -> OutputItemsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return OutputItemsWithStreamingResponse(self) def retrieve( self, output_item_id: str, *, eval_id: str, run_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OutputItemRetrieveResponse: """ Get an evaluation run output item by ID. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") if not output_item_id: raise ValueError(f"Expected a non-empty value for `output_item_id` but received {output_item_id!r}") return self._get( f"/evals/{eval_id}/runs/{run_id}/output_items/{output_item_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=OutputItemRetrieveResponse, ) def list( self, run_id: str, *, eval_id: str, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, status: Literal["fail", "pass"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[OutputItemListResponse]: """ Get a list of output items for an evaluation run. Args: after: Identifier for the last output item from the previous pagination request. limit: Number of output items to retrieve. order: Sort order for output items by timestamp. Use `asc` for ascending order or `desc` for descending order. Defaults to `asc`. status: Filter output items by status. Use `failed` to filter by failed output items or `pass` to filter by passed output items. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return self._get_api_list( f"/evals/{eval_id}/runs/{run_id}/output_items", page=SyncCursorPage[OutputItemListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, "status": status, }, output_item_list_params.OutputItemListParams, ), ), model=OutputItemListResponse, ) class AsyncOutputItems(AsyncAPIResource): """Manage and run evals in the OpenAI platform.""" @cached_property def with_raw_response(self) -> AsyncOutputItemsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncOutputItemsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncOutputItemsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncOutputItemsWithStreamingResponse(self) async def retrieve( self, output_item_id: str, *, eval_id: str, run_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OutputItemRetrieveResponse: """ Get an evaluation run output item by ID. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") if not output_item_id: raise ValueError(f"Expected a non-empty value for `output_item_id` but received {output_item_id!r}") return await self._get( f"/evals/{eval_id}/runs/{run_id}/output_items/{output_item_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=OutputItemRetrieveResponse, ) def list( self, run_id: str, *, eval_id: str, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, status: Literal["fail", "pass"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[OutputItemListResponse, AsyncCursorPage[OutputItemListResponse]]: """ Get a list of output items for an evaluation run. Args: after: Identifier for the last output item from the previous pagination request. limit: Number of output items to retrieve. order: Sort order for output items by timestamp. Use `asc` for ascending order or `desc` for descending order. Defaults to `asc`. status: Filter output items by status. Use `failed` to filter by failed output items or `pass` to filter by passed output items. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return self._get_api_list( f"/evals/{eval_id}/runs/{run_id}/output_items", page=AsyncCursorPage[OutputItemListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, "status": status, }, output_item_list_params.OutputItemListParams, ), ), model=OutputItemListResponse, ) class OutputItemsWithRawResponse: def __init__(self, output_items: OutputItems) -> None: self._output_items = output_items self.retrieve = _legacy_response.to_raw_response_wrapper( output_items.retrieve, ) self.list = _legacy_response.to_raw_response_wrapper( output_items.list, ) class AsyncOutputItemsWithRawResponse: def __init__(self, output_items: AsyncOutputItems) -> None: self._output_items = output_items self.retrieve = _legacy_response.async_to_raw_response_wrapper( output_items.retrieve, ) self.list = _legacy_response.async_to_raw_response_wrapper( output_items.list, ) class OutputItemsWithStreamingResponse: def __init__(self, output_items: OutputItems) -> None: self._output_items = output_items self.retrieve = to_streamed_response_wrapper( output_items.retrieve, ) self.list = to_streamed_response_wrapper( output_items.list, ) class AsyncOutputItemsWithStreamingResponse: def __init__(self, output_items: AsyncOutputItems) -> None: self._output_items = output_items self.retrieve = async_to_streamed_response_wrapper( output_items.retrieve, ) self.list = async_to_streamed_response_wrapper( output_items.list, ) ================================================ FILE: src/openai/resources/evals/runs/runs.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Literal import httpx from .... import _legacy_response from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ...._utils import maybe_transform, async_maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from .output_items import ( OutputItems, AsyncOutputItems, OutputItemsWithRawResponse, AsyncOutputItemsWithRawResponse, OutputItemsWithStreamingResponse, AsyncOutputItemsWithStreamingResponse, ) from ....pagination import SyncCursorPage, AsyncCursorPage from ....types.evals import run_list_params, run_create_params from ...._base_client import AsyncPaginator, make_request_options from ....types.shared_params.metadata import Metadata from ....types.evals.run_list_response import RunListResponse from ....types.evals.run_cancel_response import RunCancelResponse from ....types.evals.run_create_response import RunCreateResponse from ....types.evals.run_delete_response import RunDeleteResponse from ....types.evals.run_retrieve_response import RunRetrieveResponse __all__ = ["Runs", "AsyncRuns"] class Runs(SyncAPIResource): """Manage and run evals in the OpenAI platform.""" @cached_property def output_items(self) -> OutputItems: """Manage and run evals in the OpenAI platform.""" return OutputItems(self._client) @cached_property def with_raw_response(self) -> RunsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return RunsWithRawResponse(self) @cached_property def with_streaming_response(self) -> RunsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return RunsWithStreamingResponse(self) def create( self, eval_id: str, *, data_source: run_create_params.DataSource, metadata: Optional[Metadata] | Omit = omit, name: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> RunCreateResponse: """ Kicks off a new run for a given evaluation, specifying the data source, and what model configuration to use to test. The datasource will be validated against the schema specified in the config of the evaluation. Args: data_source: Details about the run's data source. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. name: The name of the run. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") return self._post( f"/evals/{eval_id}/runs", body=maybe_transform( { "data_source": data_source, "metadata": metadata, "name": name, }, run_create_params.RunCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=RunCreateResponse, ) def retrieve( self, run_id: str, *, eval_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> RunRetrieveResponse: """ Get an evaluation run by ID. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return self._get( f"/evals/{eval_id}/runs/{run_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=RunRetrieveResponse, ) def list( self, eval_id: str, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, status: Literal["queued", "in_progress", "completed", "canceled", "failed"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[RunListResponse]: """ Get a list of runs for an evaluation. Args: after: Identifier for the last run from the previous pagination request. limit: Number of runs to retrieve. order: Sort order for runs by timestamp. Use `asc` for ascending order or `desc` for descending order. Defaults to `asc`. status: Filter runs by status. One of `queued` | `in_progress` | `failed` | `completed` | `canceled`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") return self._get_api_list( f"/evals/{eval_id}/runs", page=SyncCursorPage[RunListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, "status": status, }, run_list_params.RunListParams, ), ), model=RunListResponse, ) def delete( self, run_id: str, *, eval_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> RunDeleteResponse: """ Delete an eval run. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return self._delete( f"/evals/{eval_id}/runs/{run_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=RunDeleteResponse, ) def cancel( self, run_id: str, *, eval_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> RunCancelResponse: """ Cancel an ongoing evaluation run. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return self._post( f"/evals/{eval_id}/runs/{run_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=RunCancelResponse, ) class AsyncRuns(AsyncAPIResource): """Manage and run evals in the OpenAI platform.""" @cached_property def output_items(self) -> AsyncOutputItems: """Manage and run evals in the OpenAI platform.""" return AsyncOutputItems(self._client) @cached_property def with_raw_response(self) -> AsyncRunsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncRunsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncRunsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncRunsWithStreamingResponse(self) async def create( self, eval_id: str, *, data_source: run_create_params.DataSource, metadata: Optional[Metadata] | Omit = omit, name: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> RunCreateResponse: """ Kicks off a new run for a given evaluation, specifying the data source, and what model configuration to use to test. The datasource will be validated against the schema specified in the config of the evaluation. Args: data_source: Details about the run's data source. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. name: The name of the run. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") return await self._post( f"/evals/{eval_id}/runs", body=await async_maybe_transform( { "data_source": data_source, "metadata": metadata, "name": name, }, run_create_params.RunCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=RunCreateResponse, ) async def retrieve( self, run_id: str, *, eval_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> RunRetrieveResponse: """ Get an evaluation run by ID. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return await self._get( f"/evals/{eval_id}/runs/{run_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=RunRetrieveResponse, ) def list( self, eval_id: str, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, status: Literal["queued", "in_progress", "completed", "canceled", "failed"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[RunListResponse, AsyncCursorPage[RunListResponse]]: """ Get a list of runs for an evaluation. Args: after: Identifier for the last run from the previous pagination request. limit: Number of runs to retrieve. order: Sort order for runs by timestamp. Use `asc` for ascending order or `desc` for descending order. Defaults to `asc`. status: Filter runs by status. One of `queued` | `in_progress` | `failed` | `completed` | `canceled`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") return self._get_api_list( f"/evals/{eval_id}/runs", page=AsyncCursorPage[RunListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, "status": status, }, run_list_params.RunListParams, ), ), model=RunListResponse, ) async def delete( self, run_id: str, *, eval_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> RunDeleteResponse: """ Delete an eval run. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return await self._delete( f"/evals/{eval_id}/runs/{run_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=RunDeleteResponse, ) async def cancel( self, run_id: str, *, eval_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> RunCancelResponse: """ Cancel an ongoing evaluation run. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not eval_id: raise ValueError(f"Expected a non-empty value for `eval_id` but received {eval_id!r}") if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return await self._post( f"/evals/{eval_id}/runs/{run_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=RunCancelResponse, ) class RunsWithRawResponse: def __init__(self, runs: Runs) -> None: self._runs = runs self.create = _legacy_response.to_raw_response_wrapper( runs.create, ) self.retrieve = _legacy_response.to_raw_response_wrapper( runs.retrieve, ) self.list = _legacy_response.to_raw_response_wrapper( runs.list, ) self.delete = _legacy_response.to_raw_response_wrapper( runs.delete, ) self.cancel = _legacy_response.to_raw_response_wrapper( runs.cancel, ) @cached_property def output_items(self) -> OutputItemsWithRawResponse: """Manage and run evals in the OpenAI platform.""" return OutputItemsWithRawResponse(self._runs.output_items) class AsyncRunsWithRawResponse: def __init__(self, runs: AsyncRuns) -> None: self._runs = runs self.create = _legacy_response.async_to_raw_response_wrapper( runs.create, ) self.retrieve = _legacy_response.async_to_raw_response_wrapper( runs.retrieve, ) self.list = _legacy_response.async_to_raw_response_wrapper( runs.list, ) self.delete = _legacy_response.async_to_raw_response_wrapper( runs.delete, ) self.cancel = _legacy_response.async_to_raw_response_wrapper( runs.cancel, ) @cached_property def output_items(self) -> AsyncOutputItemsWithRawResponse: """Manage and run evals in the OpenAI platform.""" return AsyncOutputItemsWithRawResponse(self._runs.output_items) class RunsWithStreamingResponse: def __init__(self, runs: Runs) -> None: self._runs = runs self.create = to_streamed_response_wrapper( runs.create, ) self.retrieve = to_streamed_response_wrapper( runs.retrieve, ) self.list = to_streamed_response_wrapper( runs.list, ) self.delete = to_streamed_response_wrapper( runs.delete, ) self.cancel = to_streamed_response_wrapper( runs.cancel, ) @cached_property def output_items(self) -> OutputItemsWithStreamingResponse: """Manage and run evals in the OpenAI platform.""" return OutputItemsWithStreamingResponse(self._runs.output_items) class AsyncRunsWithStreamingResponse: def __init__(self, runs: AsyncRuns) -> None: self._runs = runs self.create = async_to_streamed_response_wrapper( runs.create, ) self.retrieve = async_to_streamed_response_wrapper( runs.retrieve, ) self.list = async_to_streamed_response_wrapper( runs.list, ) self.delete = async_to_streamed_response_wrapper( runs.delete, ) self.cancel = async_to_streamed_response_wrapper( runs.cancel, ) @cached_property def output_items(self) -> AsyncOutputItemsWithStreamingResponse: """Manage and run evals in the OpenAI platform.""" return AsyncOutputItemsWithStreamingResponse(self._runs.output_items) ================================================ FILE: src/openai/resources/files.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import time import typing_extensions from typing import Mapping, cast from typing_extensions import Literal import httpx from .. import _legacy_response from ..types import FilePurpose, file_list_params, file_create_params from .._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( StreamedBinaryAPIResponse, AsyncStreamedBinaryAPIResponse, to_streamed_response_wrapper, async_to_streamed_response_wrapper, to_custom_streamed_response_wrapper, async_to_custom_streamed_response_wrapper, ) from ..pagination import SyncCursorPage, AsyncCursorPage from .._base_client import AsyncPaginator, make_request_options from ..types.file_object import FileObject from ..types.file_deleted import FileDeleted from ..types.file_purpose import FilePurpose __all__ = ["Files", "AsyncFiles"] class Files(SyncAPIResource): """ Files are used to upload documents that can be used with features like Assistants and Fine-tuning. """ @cached_property def with_raw_response(self) -> FilesWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return FilesWithRawResponse(self) @cached_property def with_streaming_response(self) -> FilesWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return FilesWithStreamingResponse(self) def create( self, *, file: FileTypes, purpose: FilePurpose, expires_after: file_create_params.ExpiresAfter | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileObject: """Upload a file that can be used across various endpoints. Individual files can be up to 512 MB, and each project can store up to 2.5 TB of files in total. There is no organization-wide storage limit. - The Assistants API supports files up to 2 million tokens and of specific file types. See the [Assistants Tools guide](https://platform.openai.com/docs/assistants/tools) for details. - The Fine-tuning API only supports `.jsonl` files. The input also has certain required formats for fine-tuning [chat](https://platform.openai.com/docs/api-reference/fine-tuning/chat-input) or [completions](https://platform.openai.com/docs/api-reference/fine-tuning/completions-input) models. - The Batch API only supports `.jsonl` files up to 200 MB in size. The input also has a specific required [format](https://platform.openai.com/docs/api-reference/batch/request-input). Please [contact us](https://help.openai.com/) if you need to increase these storage limits. Args: file: The File object (not file name) to be uploaded. purpose: The intended purpose of the uploaded file. One of: - `assistants`: Used in the Assistants API - `batch`: Used in the Batch API - `fine-tune`: Used for fine-tuning - `vision`: Images used for vision fine-tuning - `user_data`: Flexible file type for any purpose - `evals`: Used for eval data sets expires_after: The expiration policy for a file. By default, files with `purpose=batch` expire after 30 days and all other files are persisted until they are manually deleted. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ body = deepcopy_minimal( { "file": file, "purpose": purpose, "expires_after": expires_after, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return self._post( "/files", body=maybe_transform(body, file_create_params.FileCreateParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FileObject, ) def retrieve( self, file_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileObject: """ Returns information about a specific file. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return self._get( f"/files/{file_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FileObject, ) def list( self, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, purpose: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[FileObject]: """Returns a list of files. Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. limit: A limit on the number of objects to be returned. Limit can range between 1 and 10,000, and the default is 10,000. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. purpose: Only return files with the given purpose. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._get_api_list( "/files", page=SyncCursorPage[FileObject], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, "purpose": purpose, }, file_list_params.FileListParams, ), ), model=FileObject, ) def delete( self, file_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileDeleted: """ Delete a file and remove it from all vector stores. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return self._delete( f"/files/{file_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FileDeleted, ) def content( self, file_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: """ Returns the contents of the specified file. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") extra_headers = {"Accept": "application/binary", **(extra_headers or {})} return self._get( f"/files/{file_id}/content", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=_legacy_response.HttpxBinaryResponseContent, ) @typing_extensions.deprecated("The `.content()` method should be used instead") def retrieve_content( self, file_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> str: """ Returns the contents of the specified file. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return self._get( f"/files/{file_id}/content", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=str, ) def wait_for_processing( self, id: str, *, poll_interval: float = 5.0, max_wait_seconds: float = 30 * 60, ) -> FileObject: """Waits for the given file to be processed, default timeout is 30 mins.""" TERMINAL_STATES = {"processed", "error", "deleted"} start = time.time() file = self.retrieve(id) while file.status not in TERMINAL_STATES: self._sleep(poll_interval) file = self.retrieve(id) if time.time() - start > max_wait_seconds: raise RuntimeError( f"Giving up on waiting for file {id} to finish processing after {max_wait_seconds} seconds." ) return file class AsyncFiles(AsyncAPIResource): """ Files are used to upload documents that can be used with features like Assistants and Fine-tuning. """ @cached_property def with_raw_response(self) -> AsyncFilesWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncFilesWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncFilesWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncFilesWithStreamingResponse(self) async def create( self, *, file: FileTypes, purpose: FilePurpose, expires_after: file_create_params.ExpiresAfter | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileObject: """Upload a file that can be used across various endpoints. Individual files can be up to 512 MB, and each project can store up to 2.5 TB of files in total. There is no organization-wide storage limit. - The Assistants API supports files up to 2 million tokens and of specific file types. See the [Assistants Tools guide](https://platform.openai.com/docs/assistants/tools) for details. - The Fine-tuning API only supports `.jsonl` files. The input also has certain required formats for fine-tuning [chat](https://platform.openai.com/docs/api-reference/fine-tuning/chat-input) or [completions](https://platform.openai.com/docs/api-reference/fine-tuning/completions-input) models. - The Batch API only supports `.jsonl` files up to 200 MB in size. The input also has a specific required [format](https://platform.openai.com/docs/api-reference/batch/request-input). Please [contact us](https://help.openai.com/) if you need to increase these storage limits. Args: file: The File object (not file name) to be uploaded. purpose: The intended purpose of the uploaded file. One of: - `assistants`: Used in the Assistants API - `batch`: Used in the Batch API - `fine-tune`: Used for fine-tuning - `vision`: Images used for vision fine-tuning - `user_data`: Flexible file type for any purpose - `evals`: Used for eval data sets expires_after: The expiration policy for a file. By default, files with `purpose=batch` expire after 30 days and all other files are persisted until they are manually deleted. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ body = deepcopy_minimal( { "file": file, "purpose": purpose, "expires_after": expires_after, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return await self._post( "/files", body=await async_maybe_transform(body, file_create_params.FileCreateParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FileObject, ) async def retrieve( self, file_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileObject: """ Returns information about a specific file. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return await self._get( f"/files/{file_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FileObject, ) def list( self, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, purpose: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[FileObject, AsyncCursorPage[FileObject]]: """Returns a list of files. Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. limit: A limit on the number of objects to be returned. Limit can range between 1 and 10,000, and the default is 10,000. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. purpose: Only return files with the given purpose. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._get_api_list( "/files", page=AsyncCursorPage[FileObject], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, "purpose": purpose, }, file_list_params.FileListParams, ), ), model=FileObject, ) async def delete( self, file_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileDeleted: """ Delete a file and remove it from all vector stores. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return await self._delete( f"/files/{file_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FileDeleted, ) async def content( self, file_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: """ Returns the contents of the specified file. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") extra_headers = {"Accept": "application/binary", **(extra_headers or {})} return await self._get( f"/files/{file_id}/content", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=_legacy_response.HttpxBinaryResponseContent, ) @typing_extensions.deprecated("The `.content()` method should be used instead") async def retrieve_content( self, file_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> str: """ Returns the contents of the specified file. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return await self._get( f"/files/{file_id}/content", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=str, ) async def wait_for_processing( self, id: str, *, poll_interval: float = 5.0, max_wait_seconds: float = 30 * 60, ) -> FileObject: """Waits for the given file to be processed, default timeout is 30 mins.""" TERMINAL_STATES = {"processed", "error", "deleted"} start = time.time() file = await self.retrieve(id) while file.status not in TERMINAL_STATES: await self._sleep(poll_interval) file = await self.retrieve(id) if time.time() - start > max_wait_seconds: raise RuntimeError( f"Giving up on waiting for file {id} to finish processing after {max_wait_seconds} seconds." ) return file class FilesWithRawResponse: def __init__(self, files: Files) -> None: self._files = files self.create = _legacy_response.to_raw_response_wrapper( files.create, ) self.retrieve = _legacy_response.to_raw_response_wrapper( files.retrieve, ) self.list = _legacy_response.to_raw_response_wrapper( files.list, ) self.delete = _legacy_response.to_raw_response_wrapper( files.delete, ) self.content = _legacy_response.to_raw_response_wrapper( files.content, ) self.retrieve_content = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( files.retrieve_content, # pyright: ignore[reportDeprecated], ) ) class AsyncFilesWithRawResponse: def __init__(self, files: AsyncFiles) -> None: self._files = files self.create = _legacy_response.async_to_raw_response_wrapper( files.create, ) self.retrieve = _legacy_response.async_to_raw_response_wrapper( files.retrieve, ) self.list = _legacy_response.async_to_raw_response_wrapper( files.list, ) self.delete = _legacy_response.async_to_raw_response_wrapper( files.delete, ) self.content = _legacy_response.async_to_raw_response_wrapper( files.content, ) self.retrieve_content = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( files.retrieve_content, # pyright: ignore[reportDeprecated], ) ) class FilesWithStreamingResponse: def __init__(self, files: Files) -> None: self._files = files self.create = to_streamed_response_wrapper( files.create, ) self.retrieve = to_streamed_response_wrapper( files.retrieve, ) self.list = to_streamed_response_wrapper( files.list, ) self.delete = to_streamed_response_wrapper( files.delete, ) self.content = to_custom_streamed_response_wrapper( files.content, StreamedBinaryAPIResponse, ) self.retrieve_content = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( files.retrieve_content, # pyright: ignore[reportDeprecated], ) ) class AsyncFilesWithStreamingResponse: def __init__(self, files: AsyncFiles) -> None: self._files = files self.create = async_to_streamed_response_wrapper( files.create, ) self.retrieve = async_to_streamed_response_wrapper( files.retrieve, ) self.list = async_to_streamed_response_wrapper( files.list, ) self.delete = async_to_streamed_response_wrapper( files.delete, ) self.content = async_to_custom_streamed_response_wrapper( files.content, AsyncStreamedBinaryAPIResponse, ) self.retrieve_content = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( files.retrieve_content, # pyright: ignore[reportDeprecated], ) ) ================================================ FILE: src/openai/resources/fine_tuning/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .jobs import ( Jobs, AsyncJobs, JobsWithRawResponse, AsyncJobsWithRawResponse, JobsWithStreamingResponse, AsyncJobsWithStreamingResponse, ) from .alpha import ( Alpha, AsyncAlpha, AlphaWithRawResponse, AsyncAlphaWithRawResponse, AlphaWithStreamingResponse, AsyncAlphaWithStreamingResponse, ) from .checkpoints import ( Checkpoints, AsyncCheckpoints, CheckpointsWithRawResponse, AsyncCheckpointsWithRawResponse, CheckpointsWithStreamingResponse, AsyncCheckpointsWithStreamingResponse, ) from .fine_tuning import ( FineTuning, AsyncFineTuning, FineTuningWithRawResponse, AsyncFineTuningWithRawResponse, FineTuningWithStreamingResponse, AsyncFineTuningWithStreamingResponse, ) __all__ = [ "Jobs", "AsyncJobs", "JobsWithRawResponse", "AsyncJobsWithRawResponse", "JobsWithStreamingResponse", "AsyncJobsWithStreamingResponse", "Checkpoints", "AsyncCheckpoints", "CheckpointsWithRawResponse", "AsyncCheckpointsWithRawResponse", "CheckpointsWithStreamingResponse", "AsyncCheckpointsWithStreamingResponse", "Alpha", "AsyncAlpha", "AlphaWithRawResponse", "AsyncAlphaWithRawResponse", "AlphaWithStreamingResponse", "AsyncAlphaWithStreamingResponse", "FineTuning", "AsyncFineTuning", "FineTuningWithRawResponse", "AsyncFineTuningWithRawResponse", "FineTuningWithStreamingResponse", "AsyncFineTuningWithStreamingResponse", ] ================================================ FILE: src/openai/resources/fine_tuning/alpha/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .alpha import ( Alpha, AsyncAlpha, AlphaWithRawResponse, AsyncAlphaWithRawResponse, AlphaWithStreamingResponse, AsyncAlphaWithStreamingResponse, ) from .graders import ( Graders, AsyncGraders, GradersWithRawResponse, AsyncGradersWithRawResponse, GradersWithStreamingResponse, AsyncGradersWithStreamingResponse, ) __all__ = [ "Graders", "AsyncGraders", "GradersWithRawResponse", "AsyncGradersWithRawResponse", "GradersWithStreamingResponse", "AsyncGradersWithStreamingResponse", "Alpha", "AsyncAlpha", "AlphaWithRawResponse", "AsyncAlphaWithRawResponse", "AlphaWithStreamingResponse", "AsyncAlphaWithStreamingResponse", ] ================================================ FILE: src/openai/resources/fine_tuning/alpha/alpha.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .graders import ( Graders, AsyncGraders, GradersWithRawResponse, AsyncGradersWithRawResponse, GradersWithStreamingResponse, AsyncGradersWithStreamingResponse, ) from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource __all__ = ["Alpha", "AsyncAlpha"] class Alpha(SyncAPIResource): @cached_property def graders(self) -> Graders: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return Graders(self._client) @cached_property def with_raw_response(self) -> AlphaWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AlphaWithRawResponse(self) @cached_property def with_streaming_response(self) -> AlphaWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AlphaWithStreamingResponse(self) class AsyncAlpha(AsyncAPIResource): @cached_property def graders(self) -> AsyncGraders: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return AsyncGraders(self._client) @cached_property def with_raw_response(self) -> AsyncAlphaWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncAlphaWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncAlphaWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncAlphaWithStreamingResponse(self) class AlphaWithRawResponse: def __init__(self, alpha: Alpha) -> None: self._alpha = alpha @cached_property def graders(self) -> GradersWithRawResponse: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return GradersWithRawResponse(self._alpha.graders) class AsyncAlphaWithRawResponse: def __init__(self, alpha: AsyncAlpha) -> None: self._alpha = alpha @cached_property def graders(self) -> AsyncGradersWithRawResponse: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return AsyncGradersWithRawResponse(self._alpha.graders) class AlphaWithStreamingResponse: def __init__(self, alpha: Alpha) -> None: self._alpha = alpha @cached_property def graders(self) -> GradersWithStreamingResponse: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return GradersWithStreamingResponse(self._alpha.graders) class AsyncAlphaWithStreamingResponse: def __init__(self, alpha: AsyncAlpha) -> None: self._alpha = alpha @cached_property def graders(self) -> AsyncGradersWithStreamingResponse: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return AsyncGradersWithStreamingResponse(self._alpha.graders) ================================================ FILE: src/openai/resources/fine_tuning/alpha/graders.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import httpx from .... import _legacy_response from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ...._utils import maybe_transform, async_maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ...._base_client import make_request_options from ....types.fine_tuning.alpha import grader_run_params, grader_validate_params from ....types.fine_tuning.alpha.grader_run_response import GraderRunResponse from ....types.fine_tuning.alpha.grader_validate_response import GraderValidateResponse __all__ = ["Graders", "AsyncGraders"] class Graders(SyncAPIResource): """Manage fine-tuning jobs to tailor a model to your specific training data.""" @cached_property def with_raw_response(self) -> GradersWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return GradersWithRawResponse(self) @cached_property def with_streaming_response(self) -> GradersWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return GradersWithStreamingResponse(self) def run( self, *, grader: grader_run_params.Grader, model_sample: str, item: object | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> GraderRunResponse: """ Run a grader. Args: grader: The grader used for the fine-tuning job. model_sample: The model sample to be evaluated. This value will be used to populate the `sample` namespace. See [the guide](https://platform.openai.com/docs/guides/graders) for more details. The `output_json` variable will be populated if the model sample is a valid JSON string. item: The dataset item provided to the grader. This will be used to populate the `item` namespace. See [the guide](https://platform.openai.com/docs/guides/graders) for more details. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._post( "/fine_tuning/alpha/graders/run", body=maybe_transform( { "grader": grader, "model_sample": model_sample, "item": item, }, grader_run_params.GraderRunParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=GraderRunResponse, ) def validate( self, *, grader: grader_validate_params.Grader, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> GraderValidateResponse: """ Validate a grader. Args: grader: The grader used for the fine-tuning job. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._post( "/fine_tuning/alpha/graders/validate", body=maybe_transform({"grader": grader}, grader_validate_params.GraderValidateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=GraderValidateResponse, ) class AsyncGraders(AsyncAPIResource): """Manage fine-tuning jobs to tailor a model to your specific training data.""" @cached_property def with_raw_response(self) -> AsyncGradersWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncGradersWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncGradersWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncGradersWithStreamingResponse(self) async def run( self, *, grader: grader_run_params.Grader, model_sample: str, item: object | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> GraderRunResponse: """ Run a grader. Args: grader: The grader used for the fine-tuning job. model_sample: The model sample to be evaluated. This value will be used to populate the `sample` namespace. See [the guide](https://platform.openai.com/docs/guides/graders) for more details. The `output_json` variable will be populated if the model sample is a valid JSON string. item: The dataset item provided to the grader. This will be used to populate the `item` namespace. See [the guide](https://platform.openai.com/docs/guides/graders) for more details. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return await self._post( "/fine_tuning/alpha/graders/run", body=await async_maybe_transform( { "grader": grader, "model_sample": model_sample, "item": item, }, grader_run_params.GraderRunParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=GraderRunResponse, ) async def validate( self, *, grader: grader_validate_params.Grader, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> GraderValidateResponse: """ Validate a grader. Args: grader: The grader used for the fine-tuning job. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return await self._post( "/fine_tuning/alpha/graders/validate", body=await async_maybe_transform({"grader": grader}, grader_validate_params.GraderValidateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=GraderValidateResponse, ) class GradersWithRawResponse: def __init__(self, graders: Graders) -> None: self._graders = graders self.run = _legacy_response.to_raw_response_wrapper( graders.run, ) self.validate = _legacy_response.to_raw_response_wrapper( graders.validate, ) class AsyncGradersWithRawResponse: def __init__(self, graders: AsyncGraders) -> None: self._graders = graders self.run = _legacy_response.async_to_raw_response_wrapper( graders.run, ) self.validate = _legacy_response.async_to_raw_response_wrapper( graders.validate, ) class GradersWithStreamingResponse: def __init__(self, graders: Graders) -> None: self._graders = graders self.run = to_streamed_response_wrapper( graders.run, ) self.validate = to_streamed_response_wrapper( graders.validate, ) class AsyncGradersWithStreamingResponse: def __init__(self, graders: AsyncGraders) -> None: self._graders = graders self.run = async_to_streamed_response_wrapper( graders.run, ) self.validate = async_to_streamed_response_wrapper( graders.validate, ) ================================================ FILE: src/openai/resources/fine_tuning/checkpoints/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .checkpoints import ( Checkpoints, AsyncCheckpoints, CheckpointsWithRawResponse, AsyncCheckpointsWithRawResponse, CheckpointsWithStreamingResponse, AsyncCheckpointsWithStreamingResponse, ) from .permissions import ( Permissions, AsyncPermissions, PermissionsWithRawResponse, AsyncPermissionsWithRawResponse, PermissionsWithStreamingResponse, AsyncPermissionsWithStreamingResponse, ) __all__ = [ "Permissions", "AsyncPermissions", "PermissionsWithRawResponse", "AsyncPermissionsWithRawResponse", "PermissionsWithStreamingResponse", "AsyncPermissionsWithStreamingResponse", "Checkpoints", "AsyncCheckpoints", "CheckpointsWithRawResponse", "AsyncCheckpointsWithRawResponse", "CheckpointsWithStreamingResponse", "AsyncCheckpointsWithStreamingResponse", ] ================================================ FILE: src/openai/resources/fine_tuning/checkpoints/checkpoints.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from ...._compat import cached_property from .permissions import ( Permissions, AsyncPermissions, PermissionsWithRawResponse, AsyncPermissionsWithRawResponse, PermissionsWithStreamingResponse, AsyncPermissionsWithStreamingResponse, ) from ...._resource import SyncAPIResource, AsyncAPIResource __all__ = ["Checkpoints", "AsyncCheckpoints"] class Checkpoints(SyncAPIResource): @cached_property def permissions(self) -> Permissions: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return Permissions(self._client) @cached_property def with_raw_response(self) -> CheckpointsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return CheckpointsWithRawResponse(self) @cached_property def with_streaming_response(self) -> CheckpointsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return CheckpointsWithStreamingResponse(self) class AsyncCheckpoints(AsyncAPIResource): @cached_property def permissions(self) -> AsyncPermissions: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return AsyncPermissions(self._client) @cached_property def with_raw_response(self) -> AsyncCheckpointsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncCheckpointsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncCheckpointsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncCheckpointsWithStreamingResponse(self) class CheckpointsWithRawResponse: def __init__(self, checkpoints: Checkpoints) -> None: self._checkpoints = checkpoints @cached_property def permissions(self) -> PermissionsWithRawResponse: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return PermissionsWithRawResponse(self._checkpoints.permissions) class AsyncCheckpointsWithRawResponse: def __init__(self, checkpoints: AsyncCheckpoints) -> None: self._checkpoints = checkpoints @cached_property def permissions(self) -> AsyncPermissionsWithRawResponse: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return AsyncPermissionsWithRawResponse(self._checkpoints.permissions) class CheckpointsWithStreamingResponse: def __init__(self, checkpoints: Checkpoints) -> None: self._checkpoints = checkpoints @cached_property def permissions(self) -> PermissionsWithStreamingResponse: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return PermissionsWithStreamingResponse(self._checkpoints.permissions) class AsyncCheckpointsWithStreamingResponse: def __init__(self, checkpoints: AsyncCheckpoints) -> None: self._checkpoints = checkpoints @cached_property def permissions(self) -> AsyncPermissionsWithStreamingResponse: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return AsyncPermissionsWithStreamingResponse(self._checkpoints.permissions) ================================================ FILE: src/openai/resources/fine_tuning/checkpoints/permissions.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import typing_extensions from typing_extensions import Literal import httpx from .... import _legacy_response from ...._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from ...._utils import maybe_transform, async_maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ....pagination import SyncPage, AsyncPage, SyncConversationCursorPage, AsyncConversationCursorPage from ...._base_client import AsyncPaginator, make_request_options from ....types.fine_tuning.checkpoints import ( permission_list_params, permission_create_params, permission_retrieve_params, ) from ....types.fine_tuning.checkpoints.permission_list_response import PermissionListResponse from ....types.fine_tuning.checkpoints.permission_create_response import PermissionCreateResponse from ....types.fine_tuning.checkpoints.permission_delete_response import PermissionDeleteResponse from ....types.fine_tuning.checkpoints.permission_retrieve_response import PermissionRetrieveResponse __all__ = ["Permissions", "AsyncPermissions"] class Permissions(SyncAPIResource): """Manage fine-tuning jobs to tailor a model to your specific training data.""" @cached_property def with_raw_response(self) -> PermissionsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return PermissionsWithRawResponse(self) @cached_property def with_streaming_response(self) -> PermissionsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return PermissionsWithStreamingResponse(self) def create( self, fine_tuned_model_checkpoint: str, *, project_ids: SequenceNotStr[str], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[PermissionCreateResponse]: """ **NOTE:** Calling this endpoint requires an [admin API key](../admin-api-keys). This enables organization owners to share fine-tuned models with other projects in their organization. Args: project_ids: The project identifiers to grant access to. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuned_model_checkpoint: raise ValueError( f"Expected a non-empty value for `fine_tuned_model_checkpoint` but received {fine_tuned_model_checkpoint!r}" ) return self._get_api_list( f"/fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions", page=SyncPage[PermissionCreateResponse], body=maybe_transform({"project_ids": project_ids}, permission_create_params.PermissionCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), model=PermissionCreateResponse, method="post", ) @typing_extensions.deprecated("Retrieve is deprecated. Please swap to the paginated list method instead.") def retrieve( self, fine_tuned_model_checkpoint: str, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["ascending", "descending"] | Omit = omit, project_id: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> PermissionRetrieveResponse: """ **NOTE:** This endpoint requires an [admin API key](../admin-api-keys). Organization owners can use this endpoint to view all permissions for a fine-tuned model checkpoint. Args: after: Identifier for the last permission ID from the previous pagination request. limit: Number of permissions to retrieve. order: The order in which to retrieve permissions. project_id: The ID of the project to get permissions for. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuned_model_checkpoint: raise ValueError( f"Expected a non-empty value for `fine_tuned_model_checkpoint` but received {fine_tuned_model_checkpoint!r}" ) return self._get( f"/fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, "project_id": project_id, }, permission_retrieve_params.PermissionRetrieveParams, ), ), cast_to=PermissionRetrieveResponse, ) def list( self, fine_tuned_model_checkpoint: str, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["ascending", "descending"] | Omit = omit, project_id: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncConversationCursorPage[PermissionListResponse]: """ **NOTE:** This endpoint requires an [admin API key](../admin-api-keys). Organization owners can use this endpoint to view all permissions for a fine-tuned model checkpoint. Args: after: Identifier for the last permission ID from the previous pagination request. limit: Number of permissions to retrieve. order: The order in which to retrieve permissions. project_id: The ID of the project to get permissions for. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuned_model_checkpoint: raise ValueError( f"Expected a non-empty value for `fine_tuned_model_checkpoint` but received {fine_tuned_model_checkpoint!r}" ) return self._get_api_list( f"/fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions", page=SyncConversationCursorPage[PermissionListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, "project_id": project_id, }, permission_list_params.PermissionListParams, ), ), model=PermissionListResponse, ) def delete( self, permission_id: str, *, fine_tuned_model_checkpoint: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> PermissionDeleteResponse: """ **NOTE:** This endpoint requires an [admin API key](../admin-api-keys). Organization owners can use this endpoint to delete a permission for a fine-tuned model checkpoint. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuned_model_checkpoint: raise ValueError( f"Expected a non-empty value for `fine_tuned_model_checkpoint` but received {fine_tuned_model_checkpoint!r}" ) if not permission_id: raise ValueError(f"Expected a non-empty value for `permission_id` but received {permission_id!r}") return self._delete( f"/fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions/{permission_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=PermissionDeleteResponse, ) class AsyncPermissions(AsyncAPIResource): """Manage fine-tuning jobs to tailor a model to your specific training data.""" @cached_property def with_raw_response(self) -> AsyncPermissionsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncPermissionsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncPermissionsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncPermissionsWithStreamingResponse(self) def create( self, fine_tuned_model_checkpoint: str, *, project_ids: SequenceNotStr[str], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[PermissionCreateResponse, AsyncPage[PermissionCreateResponse]]: """ **NOTE:** Calling this endpoint requires an [admin API key](../admin-api-keys). This enables organization owners to share fine-tuned models with other projects in their organization. Args: project_ids: The project identifiers to grant access to. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuned_model_checkpoint: raise ValueError( f"Expected a non-empty value for `fine_tuned_model_checkpoint` but received {fine_tuned_model_checkpoint!r}" ) return self._get_api_list( f"/fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions", page=AsyncPage[PermissionCreateResponse], body=maybe_transform({"project_ids": project_ids}, permission_create_params.PermissionCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), model=PermissionCreateResponse, method="post", ) @typing_extensions.deprecated("Retrieve is deprecated. Please swap to the paginated list method instead.") async def retrieve( self, fine_tuned_model_checkpoint: str, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["ascending", "descending"] | Omit = omit, project_id: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> PermissionRetrieveResponse: """ **NOTE:** This endpoint requires an [admin API key](../admin-api-keys). Organization owners can use this endpoint to view all permissions for a fine-tuned model checkpoint. Args: after: Identifier for the last permission ID from the previous pagination request. limit: Number of permissions to retrieve. order: The order in which to retrieve permissions. project_id: The ID of the project to get permissions for. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuned_model_checkpoint: raise ValueError( f"Expected a non-empty value for `fine_tuned_model_checkpoint` but received {fine_tuned_model_checkpoint!r}" ) return await self._get( f"/fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=await async_maybe_transform( { "after": after, "limit": limit, "order": order, "project_id": project_id, }, permission_retrieve_params.PermissionRetrieveParams, ), ), cast_to=PermissionRetrieveResponse, ) def list( self, fine_tuned_model_checkpoint: str, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["ascending", "descending"] | Omit = omit, project_id: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[PermissionListResponse, AsyncConversationCursorPage[PermissionListResponse]]: """ **NOTE:** This endpoint requires an [admin API key](../admin-api-keys). Organization owners can use this endpoint to view all permissions for a fine-tuned model checkpoint. Args: after: Identifier for the last permission ID from the previous pagination request. limit: Number of permissions to retrieve. order: The order in which to retrieve permissions. project_id: The ID of the project to get permissions for. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuned_model_checkpoint: raise ValueError( f"Expected a non-empty value for `fine_tuned_model_checkpoint` but received {fine_tuned_model_checkpoint!r}" ) return self._get_api_list( f"/fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions", page=AsyncConversationCursorPage[PermissionListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, "project_id": project_id, }, permission_list_params.PermissionListParams, ), ), model=PermissionListResponse, ) async def delete( self, permission_id: str, *, fine_tuned_model_checkpoint: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> PermissionDeleteResponse: """ **NOTE:** This endpoint requires an [admin API key](../admin-api-keys). Organization owners can use this endpoint to delete a permission for a fine-tuned model checkpoint. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuned_model_checkpoint: raise ValueError( f"Expected a non-empty value for `fine_tuned_model_checkpoint` but received {fine_tuned_model_checkpoint!r}" ) if not permission_id: raise ValueError(f"Expected a non-empty value for `permission_id` but received {permission_id!r}") return await self._delete( f"/fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions/{permission_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=PermissionDeleteResponse, ) class PermissionsWithRawResponse: def __init__(self, permissions: Permissions) -> None: self._permissions = permissions self.create = _legacy_response.to_raw_response_wrapper( permissions.create, ) self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( permissions.retrieve, # pyright: ignore[reportDeprecated], ) ) self.list = _legacy_response.to_raw_response_wrapper( permissions.list, ) self.delete = _legacy_response.to_raw_response_wrapper( permissions.delete, ) class AsyncPermissionsWithRawResponse: def __init__(self, permissions: AsyncPermissions) -> None: self._permissions = permissions self.create = _legacy_response.async_to_raw_response_wrapper( permissions.create, ) self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( permissions.retrieve, # pyright: ignore[reportDeprecated], ) ) self.list = _legacy_response.async_to_raw_response_wrapper( permissions.list, ) self.delete = _legacy_response.async_to_raw_response_wrapper( permissions.delete, ) class PermissionsWithStreamingResponse: def __init__(self, permissions: Permissions) -> None: self._permissions = permissions self.create = to_streamed_response_wrapper( permissions.create, ) self.retrieve = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( permissions.retrieve, # pyright: ignore[reportDeprecated], ) ) self.list = to_streamed_response_wrapper( permissions.list, ) self.delete = to_streamed_response_wrapper( permissions.delete, ) class AsyncPermissionsWithStreamingResponse: def __init__(self, permissions: AsyncPermissions) -> None: self._permissions = permissions self.create = async_to_streamed_response_wrapper( permissions.create, ) self.retrieve = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( permissions.retrieve, # pyright: ignore[reportDeprecated], ) ) self.list = async_to_streamed_response_wrapper( permissions.list, ) self.delete = async_to_streamed_response_wrapper( permissions.delete, ) ================================================ FILE: src/openai/resources/fine_tuning/fine_tuning.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from ..._compat import cached_property from .jobs.jobs import ( Jobs, AsyncJobs, JobsWithRawResponse, AsyncJobsWithRawResponse, JobsWithStreamingResponse, AsyncJobsWithStreamingResponse, ) from ..._resource import SyncAPIResource, AsyncAPIResource from .alpha.alpha import ( Alpha, AsyncAlpha, AlphaWithRawResponse, AsyncAlphaWithRawResponse, AlphaWithStreamingResponse, AsyncAlphaWithStreamingResponse, ) from .checkpoints.checkpoints import ( Checkpoints, AsyncCheckpoints, CheckpointsWithRawResponse, AsyncCheckpointsWithRawResponse, CheckpointsWithStreamingResponse, AsyncCheckpointsWithStreamingResponse, ) __all__ = ["FineTuning", "AsyncFineTuning"] class FineTuning(SyncAPIResource): @cached_property def jobs(self) -> Jobs: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return Jobs(self._client) @cached_property def checkpoints(self) -> Checkpoints: return Checkpoints(self._client) @cached_property def alpha(self) -> Alpha: return Alpha(self._client) @cached_property def with_raw_response(self) -> FineTuningWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return FineTuningWithRawResponse(self) @cached_property def with_streaming_response(self) -> FineTuningWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return FineTuningWithStreamingResponse(self) class AsyncFineTuning(AsyncAPIResource): @cached_property def jobs(self) -> AsyncJobs: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return AsyncJobs(self._client) @cached_property def checkpoints(self) -> AsyncCheckpoints: return AsyncCheckpoints(self._client) @cached_property def alpha(self) -> AsyncAlpha: return AsyncAlpha(self._client) @cached_property def with_raw_response(self) -> AsyncFineTuningWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncFineTuningWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncFineTuningWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncFineTuningWithStreamingResponse(self) class FineTuningWithRawResponse: def __init__(self, fine_tuning: FineTuning) -> None: self._fine_tuning = fine_tuning @cached_property def jobs(self) -> JobsWithRawResponse: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return JobsWithRawResponse(self._fine_tuning.jobs) @cached_property def checkpoints(self) -> CheckpointsWithRawResponse: return CheckpointsWithRawResponse(self._fine_tuning.checkpoints) @cached_property def alpha(self) -> AlphaWithRawResponse: return AlphaWithRawResponse(self._fine_tuning.alpha) class AsyncFineTuningWithRawResponse: def __init__(self, fine_tuning: AsyncFineTuning) -> None: self._fine_tuning = fine_tuning @cached_property def jobs(self) -> AsyncJobsWithRawResponse: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return AsyncJobsWithRawResponse(self._fine_tuning.jobs) @cached_property def checkpoints(self) -> AsyncCheckpointsWithRawResponse: return AsyncCheckpointsWithRawResponse(self._fine_tuning.checkpoints) @cached_property def alpha(self) -> AsyncAlphaWithRawResponse: return AsyncAlphaWithRawResponse(self._fine_tuning.alpha) class FineTuningWithStreamingResponse: def __init__(self, fine_tuning: FineTuning) -> None: self._fine_tuning = fine_tuning @cached_property def jobs(self) -> JobsWithStreamingResponse: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return JobsWithStreamingResponse(self._fine_tuning.jobs) @cached_property def checkpoints(self) -> CheckpointsWithStreamingResponse: return CheckpointsWithStreamingResponse(self._fine_tuning.checkpoints) @cached_property def alpha(self) -> AlphaWithStreamingResponse: return AlphaWithStreamingResponse(self._fine_tuning.alpha) class AsyncFineTuningWithStreamingResponse: def __init__(self, fine_tuning: AsyncFineTuning) -> None: self._fine_tuning = fine_tuning @cached_property def jobs(self) -> AsyncJobsWithStreamingResponse: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return AsyncJobsWithStreamingResponse(self._fine_tuning.jobs) @cached_property def checkpoints(self) -> AsyncCheckpointsWithStreamingResponse: return AsyncCheckpointsWithStreamingResponse(self._fine_tuning.checkpoints) @cached_property def alpha(self) -> AsyncAlphaWithStreamingResponse: return AsyncAlphaWithStreamingResponse(self._fine_tuning.alpha) ================================================ FILE: src/openai/resources/fine_tuning/jobs/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .jobs import ( Jobs, AsyncJobs, JobsWithRawResponse, AsyncJobsWithRawResponse, JobsWithStreamingResponse, AsyncJobsWithStreamingResponse, ) from .checkpoints import ( Checkpoints, AsyncCheckpoints, CheckpointsWithRawResponse, AsyncCheckpointsWithRawResponse, CheckpointsWithStreamingResponse, AsyncCheckpointsWithStreamingResponse, ) __all__ = [ "Checkpoints", "AsyncCheckpoints", "CheckpointsWithRawResponse", "AsyncCheckpointsWithRawResponse", "CheckpointsWithStreamingResponse", "AsyncCheckpointsWithStreamingResponse", "Jobs", "AsyncJobs", "JobsWithRawResponse", "AsyncJobsWithRawResponse", "JobsWithStreamingResponse", "AsyncJobsWithStreamingResponse", ] ================================================ FILE: src/openai/resources/fine_tuning/jobs/checkpoints.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import httpx from .... import _legacy_response from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ...._utils import maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ....pagination import SyncCursorPage, AsyncCursorPage from ...._base_client import ( AsyncPaginator, make_request_options, ) from ....types.fine_tuning.jobs import checkpoint_list_params from ....types.fine_tuning.jobs.fine_tuning_job_checkpoint import FineTuningJobCheckpoint __all__ = ["Checkpoints", "AsyncCheckpoints"] class Checkpoints(SyncAPIResource): """Manage fine-tuning jobs to tailor a model to your specific training data.""" @cached_property def with_raw_response(self) -> CheckpointsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return CheckpointsWithRawResponse(self) @cached_property def with_streaming_response(self) -> CheckpointsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return CheckpointsWithStreamingResponse(self) def list( self, fine_tuning_job_id: str, *, after: str | Omit = omit, limit: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[FineTuningJobCheckpoint]: """ List checkpoints for a fine-tuning job. Args: after: Identifier for the last checkpoint ID from the previous pagination request. limit: Number of checkpoints to retrieve. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuning_job_id: raise ValueError(f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}") return self._get_api_list( f"/fine_tuning/jobs/{fine_tuning_job_id}/checkpoints", page=SyncCursorPage[FineTuningJobCheckpoint], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, }, checkpoint_list_params.CheckpointListParams, ), ), model=FineTuningJobCheckpoint, ) class AsyncCheckpoints(AsyncAPIResource): """Manage fine-tuning jobs to tailor a model to your specific training data.""" @cached_property def with_raw_response(self) -> AsyncCheckpointsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncCheckpointsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncCheckpointsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncCheckpointsWithStreamingResponse(self) def list( self, fine_tuning_job_id: str, *, after: str | Omit = omit, limit: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[FineTuningJobCheckpoint, AsyncCursorPage[FineTuningJobCheckpoint]]: """ List checkpoints for a fine-tuning job. Args: after: Identifier for the last checkpoint ID from the previous pagination request. limit: Number of checkpoints to retrieve. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuning_job_id: raise ValueError(f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}") return self._get_api_list( f"/fine_tuning/jobs/{fine_tuning_job_id}/checkpoints", page=AsyncCursorPage[FineTuningJobCheckpoint], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, }, checkpoint_list_params.CheckpointListParams, ), ), model=FineTuningJobCheckpoint, ) class CheckpointsWithRawResponse: def __init__(self, checkpoints: Checkpoints) -> None: self._checkpoints = checkpoints self.list = _legacy_response.to_raw_response_wrapper( checkpoints.list, ) class AsyncCheckpointsWithRawResponse: def __init__(self, checkpoints: AsyncCheckpoints) -> None: self._checkpoints = checkpoints self.list = _legacy_response.async_to_raw_response_wrapper( checkpoints.list, ) class CheckpointsWithStreamingResponse: def __init__(self, checkpoints: Checkpoints) -> None: self._checkpoints = checkpoints self.list = to_streamed_response_wrapper( checkpoints.list, ) class AsyncCheckpointsWithStreamingResponse: def __init__(self, checkpoints: AsyncCheckpoints) -> None: self._checkpoints = checkpoints self.list = async_to_streamed_response_wrapper( checkpoints.list, ) ================================================ FILE: src/openai/resources/fine_tuning/jobs/jobs.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Union, Iterable, Optional from typing_extensions import Literal import httpx from .... import _legacy_response from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ...._utils import maybe_transform, async_maybe_transform from ...._compat import cached_property from .checkpoints import ( Checkpoints, AsyncCheckpoints, CheckpointsWithRawResponse, AsyncCheckpointsWithRawResponse, CheckpointsWithStreamingResponse, AsyncCheckpointsWithStreamingResponse, ) from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ....pagination import SyncCursorPage, AsyncCursorPage from ...._base_client import ( AsyncPaginator, make_request_options, ) from ....types.fine_tuning import job_list_params, job_create_params, job_list_events_params from ....types.shared_params.metadata import Metadata from ....types.fine_tuning.fine_tuning_job import FineTuningJob from ....types.fine_tuning.fine_tuning_job_event import FineTuningJobEvent __all__ = ["Jobs", "AsyncJobs"] class Jobs(SyncAPIResource): """Manage fine-tuning jobs to tailor a model to your specific training data.""" @cached_property def checkpoints(self) -> Checkpoints: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return Checkpoints(self._client) @cached_property def with_raw_response(self) -> JobsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return JobsWithRawResponse(self) @cached_property def with_streaming_response(self) -> JobsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return JobsWithStreamingResponse(self) def create( self, *, model: Union[str, Literal["babbage-002", "davinci-002", "gpt-3.5-turbo", "gpt-4o-mini"]], training_file: str, hyperparameters: job_create_params.Hyperparameters | Omit = omit, integrations: Optional[Iterable[job_create_params.Integration]] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, method: job_create_params.Method | Omit = omit, seed: Optional[int] | Omit = omit, suffix: Optional[str] | Omit = omit, validation_file: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FineTuningJob: """ Creates a fine-tuning job which begins the process of creating a new model from a given dataset. Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. [Learn more about fine-tuning](https://platform.openai.com/docs/guides/model-optimization) Args: model: The name of the model to fine-tune. You can select one of the [supported models](https://platform.openai.com/docs/guides/fine-tuning#which-models-can-be-fine-tuned). training_file: The ID of an uploaded file that contains training data. See [upload file](https://platform.openai.com/docs/api-reference/files/create) for how to upload a file. Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with the purpose `fine-tune`. The contents of the file should differ depending on if the model uses the [chat](https://platform.openai.com/docs/api-reference/fine-tuning/chat-input), [completions](https://platform.openai.com/docs/api-reference/fine-tuning/completions-input) format, or if the fine-tuning method uses the [preference](https://platform.openai.com/docs/api-reference/fine-tuning/preference-input) format. See the [fine-tuning guide](https://platform.openai.com/docs/guides/model-optimization) for more details. hyperparameters: The hyperparameters used for the fine-tuning job. This value is now deprecated in favor of `method`, and should be passed in under the `method` parameter. integrations: A list of integrations to enable for your fine-tuning job. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. method: The method used for fine-tuning. seed: The seed controls the reproducibility of the job. Passing in the same seed and job parameters should produce the same results, but may differ in rare cases. If a seed is not specified, one will be generated for you. suffix: A string of up to 64 characters that will be added to your fine-tuned model name. For example, a `suffix` of "custom-model-name" would produce a model name like `ft:gpt-4o-mini:openai:custom-model-name:7p4lURel`. validation_file: The ID of an uploaded file that contains validation data. If you provide this file, the data is used to generate validation metrics periodically during fine-tuning. These metrics can be viewed in the fine-tuning results file. The same data should not be present in both train and validation files. Your dataset must be formatted as a JSONL file. You must upload your file with the purpose `fine-tune`. See the [fine-tuning guide](https://platform.openai.com/docs/guides/model-optimization) for more details. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._post( "/fine_tuning/jobs", body=maybe_transform( { "model": model, "training_file": training_file, "hyperparameters": hyperparameters, "integrations": integrations, "metadata": metadata, "method": method, "seed": seed, "suffix": suffix, "validation_file": validation_file, }, job_create_params.JobCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FineTuningJob, ) def retrieve( self, fine_tuning_job_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FineTuningJob: """ Get info about a fine-tuning job. [Learn more about fine-tuning](https://platform.openai.com/docs/guides/model-optimization) Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuning_job_id: raise ValueError(f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}") return self._get( f"/fine_tuning/jobs/{fine_tuning_job_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FineTuningJob, ) def list( self, *, after: str | Omit = omit, limit: int | Omit = omit, metadata: Optional[Dict[str, str]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[FineTuningJob]: """ List your organization's fine-tuning jobs Args: after: Identifier for the last job from the previous pagination request. limit: Number of fine-tuning jobs to retrieve. metadata: Optional metadata filter. To filter, use the syntax `metadata[k]=v`. Alternatively, set `metadata=null` to indicate no metadata. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._get_api_list( "/fine_tuning/jobs", page=SyncCursorPage[FineTuningJob], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "metadata": metadata, }, job_list_params.JobListParams, ), ), model=FineTuningJob, ) def cancel( self, fine_tuning_job_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FineTuningJob: """ Immediately cancel a fine-tune job. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuning_job_id: raise ValueError(f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}") return self._post( f"/fine_tuning/jobs/{fine_tuning_job_id}/cancel", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FineTuningJob, ) def list_events( self, fine_tuning_job_id: str, *, after: str | Omit = omit, limit: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[FineTuningJobEvent]: """ Get status updates for a fine-tuning job. Args: after: Identifier for the last event from the previous pagination request. limit: Number of events to retrieve. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuning_job_id: raise ValueError(f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}") return self._get_api_list( f"/fine_tuning/jobs/{fine_tuning_job_id}/events", page=SyncCursorPage[FineTuningJobEvent], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, }, job_list_events_params.JobListEventsParams, ), ), model=FineTuningJobEvent, ) def pause( self, fine_tuning_job_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FineTuningJob: """ Pause a fine-tune job. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuning_job_id: raise ValueError(f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}") return self._post( f"/fine_tuning/jobs/{fine_tuning_job_id}/pause", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FineTuningJob, ) def resume( self, fine_tuning_job_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FineTuningJob: """ Resume a fine-tune job. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuning_job_id: raise ValueError(f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}") return self._post( f"/fine_tuning/jobs/{fine_tuning_job_id}/resume", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FineTuningJob, ) class AsyncJobs(AsyncAPIResource): """Manage fine-tuning jobs to tailor a model to your specific training data.""" @cached_property def checkpoints(self) -> AsyncCheckpoints: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return AsyncCheckpoints(self._client) @cached_property def with_raw_response(self) -> AsyncJobsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncJobsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncJobsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncJobsWithStreamingResponse(self) async def create( self, *, model: Union[str, Literal["babbage-002", "davinci-002", "gpt-3.5-turbo", "gpt-4o-mini"]], training_file: str, hyperparameters: job_create_params.Hyperparameters | Omit = omit, integrations: Optional[Iterable[job_create_params.Integration]] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, method: job_create_params.Method | Omit = omit, seed: Optional[int] | Omit = omit, suffix: Optional[str] | Omit = omit, validation_file: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FineTuningJob: """ Creates a fine-tuning job which begins the process of creating a new model from a given dataset. Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. [Learn more about fine-tuning](https://platform.openai.com/docs/guides/model-optimization) Args: model: The name of the model to fine-tune. You can select one of the [supported models](https://platform.openai.com/docs/guides/fine-tuning#which-models-can-be-fine-tuned). training_file: The ID of an uploaded file that contains training data. See [upload file](https://platform.openai.com/docs/api-reference/files/create) for how to upload a file. Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with the purpose `fine-tune`. The contents of the file should differ depending on if the model uses the [chat](https://platform.openai.com/docs/api-reference/fine-tuning/chat-input), [completions](https://platform.openai.com/docs/api-reference/fine-tuning/completions-input) format, or if the fine-tuning method uses the [preference](https://platform.openai.com/docs/api-reference/fine-tuning/preference-input) format. See the [fine-tuning guide](https://platform.openai.com/docs/guides/model-optimization) for more details. hyperparameters: The hyperparameters used for the fine-tuning job. This value is now deprecated in favor of `method`, and should be passed in under the `method` parameter. integrations: A list of integrations to enable for your fine-tuning job. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. method: The method used for fine-tuning. seed: The seed controls the reproducibility of the job. Passing in the same seed and job parameters should produce the same results, but may differ in rare cases. If a seed is not specified, one will be generated for you. suffix: A string of up to 64 characters that will be added to your fine-tuned model name. For example, a `suffix` of "custom-model-name" would produce a model name like `ft:gpt-4o-mini:openai:custom-model-name:7p4lURel`. validation_file: The ID of an uploaded file that contains validation data. If you provide this file, the data is used to generate validation metrics periodically during fine-tuning. These metrics can be viewed in the fine-tuning results file. The same data should not be present in both train and validation files. Your dataset must be formatted as a JSONL file. You must upload your file with the purpose `fine-tune`. See the [fine-tuning guide](https://platform.openai.com/docs/guides/model-optimization) for more details. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return await self._post( "/fine_tuning/jobs", body=await async_maybe_transform( { "model": model, "training_file": training_file, "hyperparameters": hyperparameters, "integrations": integrations, "metadata": metadata, "method": method, "seed": seed, "suffix": suffix, "validation_file": validation_file, }, job_create_params.JobCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FineTuningJob, ) async def retrieve( self, fine_tuning_job_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FineTuningJob: """ Get info about a fine-tuning job. [Learn more about fine-tuning](https://platform.openai.com/docs/guides/model-optimization) Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuning_job_id: raise ValueError(f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}") return await self._get( f"/fine_tuning/jobs/{fine_tuning_job_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FineTuningJob, ) def list( self, *, after: str | Omit = omit, limit: int | Omit = omit, metadata: Optional[Dict[str, str]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[FineTuningJob, AsyncCursorPage[FineTuningJob]]: """ List your organization's fine-tuning jobs Args: after: Identifier for the last job from the previous pagination request. limit: Number of fine-tuning jobs to retrieve. metadata: Optional metadata filter. To filter, use the syntax `metadata[k]=v`. Alternatively, set `metadata=null` to indicate no metadata. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._get_api_list( "/fine_tuning/jobs", page=AsyncCursorPage[FineTuningJob], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "metadata": metadata, }, job_list_params.JobListParams, ), ), model=FineTuningJob, ) async def cancel( self, fine_tuning_job_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FineTuningJob: """ Immediately cancel a fine-tune job. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuning_job_id: raise ValueError(f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}") return await self._post( f"/fine_tuning/jobs/{fine_tuning_job_id}/cancel", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FineTuningJob, ) def list_events( self, fine_tuning_job_id: str, *, after: str | Omit = omit, limit: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[FineTuningJobEvent, AsyncCursorPage[FineTuningJobEvent]]: """ Get status updates for a fine-tuning job. Args: after: Identifier for the last event from the previous pagination request. limit: Number of events to retrieve. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuning_job_id: raise ValueError(f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}") return self._get_api_list( f"/fine_tuning/jobs/{fine_tuning_job_id}/events", page=AsyncCursorPage[FineTuningJobEvent], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, }, job_list_events_params.JobListEventsParams, ), ), model=FineTuningJobEvent, ) async def pause( self, fine_tuning_job_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FineTuningJob: """ Pause a fine-tune job. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuning_job_id: raise ValueError(f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}") return await self._post( f"/fine_tuning/jobs/{fine_tuning_job_id}/pause", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FineTuningJob, ) async def resume( self, fine_tuning_job_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FineTuningJob: """ Resume a fine-tune job. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not fine_tuning_job_id: raise ValueError(f"Expected a non-empty value for `fine_tuning_job_id` but received {fine_tuning_job_id!r}") return await self._post( f"/fine_tuning/jobs/{fine_tuning_job_id}/resume", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=FineTuningJob, ) class JobsWithRawResponse: def __init__(self, jobs: Jobs) -> None: self._jobs = jobs self.create = _legacy_response.to_raw_response_wrapper( jobs.create, ) self.retrieve = _legacy_response.to_raw_response_wrapper( jobs.retrieve, ) self.list = _legacy_response.to_raw_response_wrapper( jobs.list, ) self.cancel = _legacy_response.to_raw_response_wrapper( jobs.cancel, ) self.list_events = _legacy_response.to_raw_response_wrapper( jobs.list_events, ) self.pause = _legacy_response.to_raw_response_wrapper( jobs.pause, ) self.resume = _legacy_response.to_raw_response_wrapper( jobs.resume, ) @cached_property def checkpoints(self) -> CheckpointsWithRawResponse: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return CheckpointsWithRawResponse(self._jobs.checkpoints) class AsyncJobsWithRawResponse: def __init__(self, jobs: AsyncJobs) -> None: self._jobs = jobs self.create = _legacy_response.async_to_raw_response_wrapper( jobs.create, ) self.retrieve = _legacy_response.async_to_raw_response_wrapper( jobs.retrieve, ) self.list = _legacy_response.async_to_raw_response_wrapper( jobs.list, ) self.cancel = _legacy_response.async_to_raw_response_wrapper( jobs.cancel, ) self.list_events = _legacy_response.async_to_raw_response_wrapper( jobs.list_events, ) self.pause = _legacy_response.async_to_raw_response_wrapper( jobs.pause, ) self.resume = _legacy_response.async_to_raw_response_wrapper( jobs.resume, ) @cached_property def checkpoints(self) -> AsyncCheckpointsWithRawResponse: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return AsyncCheckpointsWithRawResponse(self._jobs.checkpoints) class JobsWithStreamingResponse: def __init__(self, jobs: Jobs) -> None: self._jobs = jobs self.create = to_streamed_response_wrapper( jobs.create, ) self.retrieve = to_streamed_response_wrapper( jobs.retrieve, ) self.list = to_streamed_response_wrapper( jobs.list, ) self.cancel = to_streamed_response_wrapper( jobs.cancel, ) self.list_events = to_streamed_response_wrapper( jobs.list_events, ) self.pause = to_streamed_response_wrapper( jobs.pause, ) self.resume = to_streamed_response_wrapper( jobs.resume, ) @cached_property def checkpoints(self) -> CheckpointsWithStreamingResponse: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return CheckpointsWithStreamingResponse(self._jobs.checkpoints) class AsyncJobsWithStreamingResponse: def __init__(self, jobs: AsyncJobs) -> None: self._jobs = jobs self.create = async_to_streamed_response_wrapper( jobs.create, ) self.retrieve = async_to_streamed_response_wrapper( jobs.retrieve, ) self.list = async_to_streamed_response_wrapper( jobs.list, ) self.cancel = async_to_streamed_response_wrapper( jobs.cancel, ) self.list_events = async_to_streamed_response_wrapper( jobs.list_events, ) self.pause = async_to_streamed_response_wrapper( jobs.pause, ) self.resume = async_to_streamed_response_wrapper( jobs.resume, ) @cached_property def checkpoints(self) -> AsyncCheckpointsWithStreamingResponse: """Manage fine-tuning jobs to tailor a model to your specific training data.""" return AsyncCheckpointsWithStreamingResponse(self._jobs.checkpoints) ================================================ FILE: src/openai/resources/images.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Mapping, Optional, cast from typing_extensions import Literal, overload import httpx from .. import _legacy_response from ..types import image_edit_params, image_generate_params, image_create_variation_params from .._types import Body, Omit, Query, Headers, NotGiven, FileTypes, SequenceNotStr, omit, not_given from .._utils import extract_files, required_args, maybe_transform, deepcopy_minimal, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from .._streaming import Stream, AsyncStream from .._base_client import make_request_options from ..types.image_model import ImageModel from ..types.images_response import ImagesResponse from ..types.image_gen_stream_event import ImageGenStreamEvent from ..types.image_edit_stream_event import ImageEditStreamEvent __all__ = ["Images", "AsyncImages"] class Images(SyncAPIResource): """Given a prompt and/or an input image, the model will generate a new image.""" @cached_property def with_raw_response(self) -> ImagesWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return ImagesWithRawResponse(self) @cached_property def with_streaming_response(self) -> ImagesWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return ImagesWithStreamingResponse(self) def create_variation( self, *, image: FileTypes, model: Union[str, ImageModel, None] | Omit = omit, n: Optional[int] | Omit = omit, response_format: Optional[Literal["url", "b64_json"]] | Omit = omit, size: Optional[Literal["256x256", "512x512", "1024x1024"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ImagesResponse: """Creates a variation of a given image. This endpoint only supports `dall-e-2`. Args: image: The image to use as the basis for the variation(s). Must be a valid PNG file, less than 4MB, and square. model: The model to use for image generation. Only `dall-e-2` is supported at this time. n: The number of images to generate. Must be between 1 and 10. response_format: The format in which the generated images are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. size: The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ body = deepcopy_minimal( { "image": image, "model": model, "n": n, "response_format": response_format, "size": size, "user": user, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["image"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return self._post( "/images/variations", body=maybe_transform(body, image_create_variation_params.ImageCreateVariationParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ImagesResponse, ) @overload def edit( self, *, image: Union[FileTypes, SequenceNotStr[FileTypes]], prompt: str, background: Optional[Literal["transparent", "opaque", "auto"]] | Omit = omit, input_fidelity: Optional[Literal["high", "low"]] | Omit = omit, mask: FileTypes | Omit = omit, model: Union[str, ImageModel, None] | Omit = omit, n: Optional[int] | Omit = omit, output_compression: Optional[int] | Omit = omit, output_format: Optional[Literal["png", "jpeg", "webp"]] | Omit = omit, partial_images: Optional[int] | Omit = omit, quality: Optional[Literal["standard", "low", "medium", "high", "auto"]] | Omit = omit, response_format: Optional[Literal["url", "b64_json"]] | Omit = omit, size: Optional[Literal["256x256", "512x512", "1024x1024", "1536x1024", "1024x1536", "auto"]] | Omit = omit, stream: Optional[Literal[False]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ImagesResponse: """Creates an edited or extended image given one or more source images and a prompt. This endpoint supports GPT Image models (`gpt-image-1.5`, `gpt-image-1`, `gpt-image-1-mini`, and `chatgpt-image-latest`) and `dall-e-2`. Args: image: The image(s) to edit. Must be a supported image file or an array of images. For the GPT image models (`gpt-image-1`, `gpt-image-1-mini`, and `gpt-image-1.5`), each image should be a `png`, `webp`, or `jpg` file less than 50MB. You can provide up to 16 images. `chatgpt-image-latest` follows the same input constraints as GPT image models. For `dall-e-2`, you can only provide one image, and it should be a square `png` file less than 4MB. prompt: A text description of the desired image(s). The maximum length is 1000 characters for `dall-e-2`, and 32000 characters for the GPT image models. background: Allows to set transparency for the background of the generated image(s). This parameter is only supported for the GPT image models. Must be one of `transparent`, `opaque` or `auto` (default value). When `auto` is used, the model will automatically determine the best background for the image. If `transparent`, the output format needs to support transparency, so it should be set to either `png` (default value) or `webp`. input_fidelity: Control how much effort the model will exert to match the style and features, especially facial features, of input images. This parameter is only supported for `gpt-image-1` and `gpt-image-1.5` and later models, unsupported for `gpt-image-1-mini`. Supports `high` and `low`. Defaults to `low`. mask: An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where `image` should be edited. If there are multiple images provided, the mask will be applied on the first image. Must be a valid PNG file, less than 4MB, and have the same dimensions as `image`. model: The model to use for image generation. Defaults to `gpt-image-1.5`. n: The number of images to generate. Must be between 1 and 10. output_compression: The compression level (0-100%) for the generated images. This parameter is only supported for the GPT image models with the `webp` or `jpeg` output formats, and defaults to 100. output_format: The format in which the generated images are returned. This parameter is only supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`. The default value is `png`. partial_images: The number of partial images to generate. This parameter is used for streaming responses that return partial images. Value must be between 0 and 3. When set to 0, the response will be a single image sent in one streaming event. Note that the final image may be sent before the full number of partial images are generated if the full image is generated more quickly. quality: The quality of the image that will be generated for GPT image models. Defaults to `auto`. response_format: The format in which the generated images are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. This parameter is only supported for `dall-e-2` (default is `url` for `dall-e-2`), as GPT image models always return base64-encoded images. size: The size of the generated images. Must be one of `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto` (default value) for the GPT image models, and one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`. stream: Edit the image in streaming mode. Defaults to `false`. See the [Image generation guide](https://platform.openai.com/docs/guides/image-generation) for more information. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload def edit( self, *, image: Union[FileTypes, SequenceNotStr[FileTypes]], prompt: str, stream: Literal[True], background: Optional[Literal["transparent", "opaque", "auto"]] | Omit = omit, input_fidelity: Optional[Literal["high", "low"]] | Omit = omit, mask: FileTypes | Omit = omit, model: Union[str, ImageModel, None] | Omit = omit, n: Optional[int] | Omit = omit, output_compression: Optional[int] | Omit = omit, output_format: Optional[Literal["png", "jpeg", "webp"]] | Omit = omit, partial_images: Optional[int] | Omit = omit, quality: Optional[Literal["standard", "low", "medium", "high", "auto"]] | Omit = omit, response_format: Optional[Literal["url", "b64_json"]] | Omit = omit, size: Optional[Literal["256x256", "512x512", "1024x1024", "1536x1024", "1024x1536", "auto"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Stream[ImageEditStreamEvent]: """Creates an edited or extended image given one or more source images and a prompt. This endpoint supports GPT Image models (`gpt-image-1.5`, `gpt-image-1`, `gpt-image-1-mini`, and `chatgpt-image-latest`) and `dall-e-2`. Args: image: The image(s) to edit. Must be a supported image file or an array of images. For the GPT image models (`gpt-image-1`, `gpt-image-1-mini`, and `gpt-image-1.5`), each image should be a `png`, `webp`, or `jpg` file less than 50MB. You can provide up to 16 images. `chatgpt-image-latest` follows the same input constraints as GPT image models. For `dall-e-2`, you can only provide one image, and it should be a square `png` file less than 4MB. prompt: A text description of the desired image(s). The maximum length is 1000 characters for `dall-e-2`, and 32000 characters for the GPT image models. stream: Edit the image in streaming mode. Defaults to `false`. See the [Image generation guide](https://platform.openai.com/docs/guides/image-generation) for more information. background: Allows to set transparency for the background of the generated image(s). This parameter is only supported for the GPT image models. Must be one of `transparent`, `opaque` or `auto` (default value). When `auto` is used, the model will automatically determine the best background for the image. If `transparent`, the output format needs to support transparency, so it should be set to either `png` (default value) or `webp`. input_fidelity: Control how much effort the model will exert to match the style and features, especially facial features, of input images. This parameter is only supported for `gpt-image-1` and `gpt-image-1.5` and later models, unsupported for `gpt-image-1-mini`. Supports `high` and `low`. Defaults to `low`. mask: An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where `image` should be edited. If there are multiple images provided, the mask will be applied on the first image. Must be a valid PNG file, less than 4MB, and have the same dimensions as `image`. model: The model to use for image generation. Defaults to `gpt-image-1.5`. n: The number of images to generate. Must be between 1 and 10. output_compression: The compression level (0-100%) for the generated images. This parameter is only supported for the GPT image models with the `webp` or `jpeg` output formats, and defaults to 100. output_format: The format in which the generated images are returned. This parameter is only supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`. The default value is `png`. partial_images: The number of partial images to generate. This parameter is used for streaming responses that return partial images. Value must be between 0 and 3. When set to 0, the response will be a single image sent in one streaming event. Note that the final image may be sent before the full number of partial images are generated if the full image is generated more quickly. quality: The quality of the image that will be generated for GPT image models. Defaults to `auto`. response_format: The format in which the generated images are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. This parameter is only supported for `dall-e-2` (default is `url` for `dall-e-2`), as GPT image models always return base64-encoded images. size: The size of the generated images. Must be one of `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto` (default value) for the GPT image models, and one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload def edit( self, *, image: Union[FileTypes, SequenceNotStr[FileTypes]], prompt: str, stream: bool, background: Optional[Literal["transparent", "opaque", "auto"]] | Omit = omit, input_fidelity: Optional[Literal["high", "low"]] | Omit = omit, mask: FileTypes | Omit = omit, model: Union[str, ImageModel, None] | Omit = omit, n: Optional[int] | Omit = omit, output_compression: Optional[int] | Omit = omit, output_format: Optional[Literal["png", "jpeg", "webp"]] | Omit = omit, partial_images: Optional[int] | Omit = omit, quality: Optional[Literal["standard", "low", "medium", "high", "auto"]] | Omit = omit, response_format: Optional[Literal["url", "b64_json"]] | Omit = omit, size: Optional[Literal["256x256", "512x512", "1024x1024", "1536x1024", "1024x1536", "auto"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ImagesResponse | Stream[ImageEditStreamEvent]: """Creates an edited or extended image given one or more source images and a prompt. This endpoint supports GPT Image models (`gpt-image-1.5`, `gpt-image-1`, `gpt-image-1-mini`, and `chatgpt-image-latest`) and `dall-e-2`. Args: image: The image(s) to edit. Must be a supported image file or an array of images. For the GPT image models (`gpt-image-1`, `gpt-image-1-mini`, and `gpt-image-1.5`), each image should be a `png`, `webp`, or `jpg` file less than 50MB. You can provide up to 16 images. `chatgpt-image-latest` follows the same input constraints as GPT image models. For `dall-e-2`, you can only provide one image, and it should be a square `png` file less than 4MB. prompt: A text description of the desired image(s). The maximum length is 1000 characters for `dall-e-2`, and 32000 characters for the GPT image models. stream: Edit the image in streaming mode. Defaults to `false`. See the [Image generation guide](https://platform.openai.com/docs/guides/image-generation) for more information. background: Allows to set transparency for the background of the generated image(s). This parameter is only supported for the GPT image models. Must be one of `transparent`, `opaque` or `auto` (default value). When `auto` is used, the model will automatically determine the best background for the image. If `transparent`, the output format needs to support transparency, so it should be set to either `png` (default value) or `webp`. input_fidelity: Control how much effort the model will exert to match the style and features, especially facial features, of input images. This parameter is only supported for `gpt-image-1` and `gpt-image-1.5` and later models, unsupported for `gpt-image-1-mini`. Supports `high` and `low`. Defaults to `low`. mask: An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where `image` should be edited. If there are multiple images provided, the mask will be applied on the first image. Must be a valid PNG file, less than 4MB, and have the same dimensions as `image`. model: The model to use for image generation. Defaults to `gpt-image-1.5`. n: The number of images to generate. Must be between 1 and 10. output_compression: The compression level (0-100%) for the generated images. This parameter is only supported for the GPT image models with the `webp` or `jpeg` output formats, and defaults to 100. output_format: The format in which the generated images are returned. This parameter is only supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`. The default value is `png`. partial_images: The number of partial images to generate. This parameter is used for streaming responses that return partial images. Value must be between 0 and 3. When set to 0, the response will be a single image sent in one streaming event. Note that the final image may be sent before the full number of partial images are generated if the full image is generated more quickly. quality: The quality of the image that will be generated for GPT image models. Defaults to `auto`. response_format: The format in which the generated images are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. This parameter is only supported for `dall-e-2` (default is `url` for `dall-e-2`), as GPT image models always return base64-encoded images. size: The size of the generated images. Must be one of `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto` (default value) for the GPT image models, and one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @required_args(["image", "prompt"], ["image", "prompt", "stream"]) def edit( self, *, image: Union[FileTypes, SequenceNotStr[FileTypes]], prompt: str, background: Optional[Literal["transparent", "opaque", "auto"]] | Omit = omit, input_fidelity: Optional[Literal["high", "low"]] | Omit = omit, mask: FileTypes | Omit = omit, model: Union[str, ImageModel, None] | Omit = omit, n: Optional[int] | Omit = omit, output_compression: Optional[int] | Omit = omit, output_format: Optional[Literal["png", "jpeg", "webp"]] | Omit = omit, partial_images: Optional[int] | Omit = omit, quality: Optional[Literal["standard", "low", "medium", "high", "auto"]] | Omit = omit, response_format: Optional[Literal["url", "b64_json"]] | Omit = omit, size: Optional[Literal["256x256", "512x512", "1024x1024", "1536x1024", "1024x1536", "auto"]] | Omit = omit, stream: Optional[Literal[False]] | Literal[True] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ImagesResponse | Stream[ImageEditStreamEvent]: body = deepcopy_minimal( { "image": image, "prompt": prompt, "background": background, "input_fidelity": input_fidelity, "mask": mask, "model": model, "n": n, "output_compression": output_compression, "output_format": output_format, "partial_images": partial_images, "quality": quality, "response_format": response_format, "size": size, "stream": stream, "user": user, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["image"], ["image", ""], ["mask"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return self._post( "/images/edits", body=maybe_transform( body, image_edit_params.ImageEditParamsStreaming if stream else image_edit_params.ImageEditParamsNonStreaming, ), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ImagesResponse, stream=stream or False, stream_cls=Stream[ImageEditStreamEvent], ) @overload def generate( self, *, prompt: str, background: Optional[Literal["transparent", "opaque", "auto"]] | Omit = omit, model: Union[str, ImageModel, None] | Omit = omit, moderation: Optional[Literal["low", "auto"]] | Omit = omit, n: Optional[int] | Omit = omit, output_compression: Optional[int] | Omit = omit, output_format: Optional[Literal["png", "jpeg", "webp"]] | Omit = omit, partial_images: Optional[int] | Omit = omit, quality: Optional[Literal["standard", "hd", "low", "medium", "high", "auto"]] | Omit = omit, response_format: Optional[Literal["url", "b64_json"]] | Omit = omit, size: Optional[ Literal["auto", "1024x1024", "1536x1024", "1024x1536", "256x256", "512x512", "1792x1024", "1024x1792"] ] | Omit = omit, stream: Optional[Literal[False]] | Omit = omit, style: Optional[Literal["vivid", "natural"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ImagesResponse: """ Creates an image given a prompt. [Learn more](https://platform.openai.com/docs/guides/images). Args: prompt: A text description of the desired image(s). The maximum length is 32000 characters for the GPT image models, 1000 characters for `dall-e-2` and 4000 characters for `dall-e-3`. background: Allows to set transparency for the background of the generated image(s). This parameter is only supported for the GPT image models. Must be one of `transparent`, `opaque` or `auto` (default value). When `auto` is used, the model will automatically determine the best background for the image. If `transparent`, the output format needs to support transparency, so it should be set to either `png` (default value) or `webp`. model: The model to use for image generation. One of `dall-e-2`, `dall-e-3`, or a GPT image model (`gpt-image-1`, `gpt-image-1-mini`, `gpt-image-1.5`). Defaults to `dall-e-2` unless a parameter specific to the GPT image models is used. moderation: Control the content-moderation level for images generated by the GPT image models. Must be either `low` for less restrictive filtering or `auto` (default value). n: The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is supported. output_compression: The compression level (0-100%) for the generated images. This parameter is only supported for the GPT image models with the `webp` or `jpeg` output formats, and defaults to 100. output_format: The format in which the generated images are returned. This parameter is only supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`. partial_images: The number of partial images to generate. This parameter is used for streaming responses that return partial images. Value must be between 0 and 3. When set to 0, the response will be a single image sent in one streaming event. Note that the final image may be sent before the full number of partial images are generated if the full image is generated more quickly. quality: The quality of the image that will be generated. - `auto` (default value) will automatically select the best quality for the given model. - `high`, `medium` and `low` are supported for the GPT image models. - `hd` and `standard` are supported for `dall-e-3`. - `standard` is the only option for `dall-e-2`. response_format: The format in which generated images with `dall-e-2` and `dall-e-3` are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. This parameter isn't supported for the GPT image models, which always return base64-encoded images. size: The size of the generated images. Must be one of `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto` (default value) for the GPT image models, one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`, and one of `1024x1024`, `1792x1024`, or `1024x1792` for `dall-e-3`. stream: Generate the image in streaming mode. Defaults to `false`. See the [Image generation guide](https://platform.openai.com/docs/guides/image-generation) for more information. This parameter is only supported for the GPT image models. style: The style of the generated images. This parameter is only supported for `dall-e-3`. Must be one of `vivid` or `natural`. Vivid causes the model to lean towards generating hyper-real and dramatic images. Natural causes the model to produce more natural, less hyper-real looking images. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload def generate( self, *, prompt: str, stream: Literal[True], background: Optional[Literal["transparent", "opaque", "auto"]] | Omit = omit, model: Union[str, ImageModel, None] | Omit = omit, moderation: Optional[Literal["low", "auto"]] | Omit = omit, n: Optional[int] | Omit = omit, output_compression: Optional[int] | Omit = omit, output_format: Optional[Literal["png", "jpeg", "webp"]] | Omit = omit, partial_images: Optional[int] | Omit = omit, quality: Optional[Literal["standard", "hd", "low", "medium", "high", "auto"]] | Omit = omit, response_format: Optional[Literal["url", "b64_json"]] | Omit = omit, size: Optional[ Literal["auto", "1024x1024", "1536x1024", "1024x1536", "256x256", "512x512", "1792x1024", "1024x1792"] ] | Omit = omit, style: Optional[Literal["vivid", "natural"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Stream[ImageGenStreamEvent]: """ Creates an image given a prompt. [Learn more](https://platform.openai.com/docs/guides/images). Args: prompt: A text description of the desired image(s). The maximum length is 32000 characters for the GPT image models, 1000 characters for `dall-e-2` and 4000 characters for `dall-e-3`. stream: Generate the image in streaming mode. Defaults to `false`. See the [Image generation guide](https://platform.openai.com/docs/guides/image-generation) for more information. This parameter is only supported for the GPT image models. background: Allows to set transparency for the background of the generated image(s). This parameter is only supported for the GPT image models. Must be one of `transparent`, `opaque` or `auto` (default value). When `auto` is used, the model will automatically determine the best background for the image. If `transparent`, the output format needs to support transparency, so it should be set to either `png` (default value) or `webp`. model: The model to use for image generation. One of `dall-e-2`, `dall-e-3`, or a GPT image model (`gpt-image-1`, `gpt-image-1-mini`, `gpt-image-1.5`). Defaults to `dall-e-2` unless a parameter specific to the GPT image models is used. moderation: Control the content-moderation level for images generated by the GPT image models. Must be either `low` for less restrictive filtering or `auto` (default value). n: The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is supported. output_compression: The compression level (0-100%) for the generated images. This parameter is only supported for the GPT image models with the `webp` or `jpeg` output formats, and defaults to 100. output_format: The format in which the generated images are returned. This parameter is only supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`. partial_images: The number of partial images to generate. This parameter is used for streaming responses that return partial images. Value must be between 0 and 3. When set to 0, the response will be a single image sent in one streaming event. Note that the final image may be sent before the full number of partial images are generated if the full image is generated more quickly. quality: The quality of the image that will be generated. - `auto` (default value) will automatically select the best quality for the given model. - `high`, `medium` and `low` are supported for the GPT image models. - `hd` and `standard` are supported for `dall-e-3`. - `standard` is the only option for `dall-e-2`. response_format: The format in which generated images with `dall-e-2` and `dall-e-3` are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. This parameter isn't supported for the GPT image models, which always return base64-encoded images. size: The size of the generated images. Must be one of `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto` (default value) for the GPT image models, one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`, and one of `1024x1024`, `1792x1024`, or `1024x1792` for `dall-e-3`. style: The style of the generated images. This parameter is only supported for `dall-e-3`. Must be one of `vivid` or `natural`. Vivid causes the model to lean towards generating hyper-real and dramatic images. Natural causes the model to produce more natural, less hyper-real looking images. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload def generate( self, *, prompt: str, stream: bool, background: Optional[Literal["transparent", "opaque", "auto"]] | Omit = omit, model: Union[str, ImageModel, None] | Omit = omit, moderation: Optional[Literal["low", "auto"]] | Omit = omit, n: Optional[int] | Omit = omit, output_compression: Optional[int] | Omit = omit, output_format: Optional[Literal["png", "jpeg", "webp"]] | Omit = omit, partial_images: Optional[int] | Omit = omit, quality: Optional[Literal["standard", "hd", "low", "medium", "high", "auto"]] | Omit = omit, response_format: Optional[Literal["url", "b64_json"]] | Omit = omit, size: Optional[ Literal["auto", "1024x1024", "1536x1024", "1024x1536", "256x256", "512x512", "1792x1024", "1024x1792"] ] | Omit = omit, style: Optional[Literal["vivid", "natural"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ImagesResponse | Stream[ImageGenStreamEvent]: """ Creates an image given a prompt. [Learn more](https://platform.openai.com/docs/guides/images). Args: prompt: A text description of the desired image(s). The maximum length is 32000 characters for the GPT image models, 1000 characters for `dall-e-2` and 4000 characters for `dall-e-3`. stream: Generate the image in streaming mode. Defaults to `false`. See the [Image generation guide](https://platform.openai.com/docs/guides/image-generation) for more information. This parameter is only supported for the GPT image models. background: Allows to set transparency for the background of the generated image(s). This parameter is only supported for the GPT image models. Must be one of `transparent`, `opaque` or `auto` (default value). When `auto` is used, the model will automatically determine the best background for the image. If `transparent`, the output format needs to support transparency, so it should be set to either `png` (default value) or `webp`. model: The model to use for image generation. One of `dall-e-2`, `dall-e-3`, or a GPT image model (`gpt-image-1`, `gpt-image-1-mini`, `gpt-image-1.5`). Defaults to `dall-e-2` unless a parameter specific to the GPT image models is used. moderation: Control the content-moderation level for images generated by the GPT image models. Must be either `low` for less restrictive filtering or `auto` (default value). n: The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is supported. output_compression: The compression level (0-100%) for the generated images. This parameter is only supported for the GPT image models with the `webp` or `jpeg` output formats, and defaults to 100. output_format: The format in which the generated images are returned. This parameter is only supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`. partial_images: The number of partial images to generate. This parameter is used for streaming responses that return partial images. Value must be between 0 and 3. When set to 0, the response will be a single image sent in one streaming event. Note that the final image may be sent before the full number of partial images are generated if the full image is generated more quickly. quality: The quality of the image that will be generated. - `auto` (default value) will automatically select the best quality for the given model. - `high`, `medium` and `low` are supported for the GPT image models. - `hd` and `standard` are supported for `dall-e-3`. - `standard` is the only option for `dall-e-2`. response_format: The format in which generated images with `dall-e-2` and `dall-e-3` are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. This parameter isn't supported for the GPT image models, which always return base64-encoded images. size: The size of the generated images. Must be one of `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto` (default value) for the GPT image models, one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`, and one of `1024x1024`, `1792x1024`, or `1024x1792` for `dall-e-3`. style: The style of the generated images. This parameter is only supported for `dall-e-3`. Must be one of `vivid` or `natural`. Vivid causes the model to lean towards generating hyper-real and dramatic images. Natural causes the model to produce more natural, less hyper-real looking images. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @required_args(["prompt"], ["prompt", "stream"]) def generate( self, *, prompt: str, background: Optional[Literal["transparent", "opaque", "auto"]] | Omit = omit, model: Union[str, ImageModel, None] | Omit = omit, moderation: Optional[Literal["low", "auto"]] | Omit = omit, n: Optional[int] | Omit = omit, output_compression: Optional[int] | Omit = omit, output_format: Optional[Literal["png", "jpeg", "webp"]] | Omit = omit, partial_images: Optional[int] | Omit = omit, quality: Optional[Literal["standard", "hd", "low", "medium", "high", "auto"]] | Omit = omit, response_format: Optional[Literal["url", "b64_json"]] | Omit = omit, size: Optional[ Literal["auto", "1024x1024", "1536x1024", "1024x1536", "256x256", "512x512", "1792x1024", "1024x1792"] ] | Omit = omit, stream: Optional[Literal[False]] | Literal[True] | Omit = omit, style: Optional[Literal["vivid", "natural"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ImagesResponse | Stream[ImageGenStreamEvent]: return self._post( "/images/generations", body=maybe_transform( { "prompt": prompt, "background": background, "model": model, "moderation": moderation, "n": n, "output_compression": output_compression, "output_format": output_format, "partial_images": partial_images, "quality": quality, "response_format": response_format, "size": size, "stream": stream, "style": style, "user": user, }, image_generate_params.ImageGenerateParamsStreaming if stream else image_generate_params.ImageGenerateParamsNonStreaming, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ImagesResponse, stream=stream or False, stream_cls=Stream[ImageGenStreamEvent], ) class AsyncImages(AsyncAPIResource): """Given a prompt and/or an input image, the model will generate a new image.""" @cached_property def with_raw_response(self) -> AsyncImagesWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncImagesWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncImagesWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncImagesWithStreamingResponse(self) async def create_variation( self, *, image: FileTypes, model: Union[str, ImageModel, None] | Omit = omit, n: Optional[int] | Omit = omit, response_format: Optional[Literal["url", "b64_json"]] | Omit = omit, size: Optional[Literal["256x256", "512x512", "1024x1024"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ImagesResponse: """Creates a variation of a given image. This endpoint only supports `dall-e-2`. Args: image: The image to use as the basis for the variation(s). Must be a valid PNG file, less than 4MB, and square. model: The model to use for image generation. Only `dall-e-2` is supported at this time. n: The number of images to generate. Must be between 1 and 10. response_format: The format in which the generated images are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. size: The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ body = deepcopy_minimal( { "image": image, "model": model, "n": n, "response_format": response_format, "size": size, "user": user, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["image"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return await self._post( "/images/variations", body=await async_maybe_transform(body, image_create_variation_params.ImageCreateVariationParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ImagesResponse, ) @overload async def edit( self, *, image: Union[FileTypes, SequenceNotStr[FileTypes]], prompt: str, background: Optional[Literal["transparent", "opaque", "auto"]] | Omit = omit, input_fidelity: Optional[Literal["high", "low"]] | Omit = omit, mask: FileTypes | Omit = omit, model: Union[str, ImageModel, None] | Omit = omit, n: Optional[int] | Omit = omit, output_compression: Optional[int] | Omit = omit, output_format: Optional[Literal["png", "jpeg", "webp"]] | Omit = omit, partial_images: Optional[int] | Omit = omit, quality: Optional[Literal["standard", "low", "medium", "high", "auto"]] | Omit = omit, response_format: Optional[Literal["url", "b64_json"]] | Omit = omit, size: Optional[Literal["256x256", "512x512", "1024x1024", "1536x1024", "1024x1536", "auto"]] | Omit = omit, stream: Optional[Literal[False]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ImagesResponse: """Creates an edited or extended image given one or more source images and a prompt. This endpoint supports GPT Image models (`gpt-image-1.5`, `gpt-image-1`, `gpt-image-1-mini`, and `chatgpt-image-latest`) and `dall-e-2`. Args: image: The image(s) to edit. Must be a supported image file or an array of images. For the GPT image models (`gpt-image-1`, `gpt-image-1-mini`, and `gpt-image-1.5`), each image should be a `png`, `webp`, or `jpg` file less than 50MB. You can provide up to 16 images. `chatgpt-image-latest` follows the same input constraints as GPT image models. For `dall-e-2`, you can only provide one image, and it should be a square `png` file less than 4MB. prompt: A text description of the desired image(s). The maximum length is 1000 characters for `dall-e-2`, and 32000 characters for the GPT image models. background: Allows to set transparency for the background of the generated image(s). This parameter is only supported for the GPT image models. Must be one of `transparent`, `opaque` or `auto` (default value). When `auto` is used, the model will automatically determine the best background for the image. If `transparent`, the output format needs to support transparency, so it should be set to either `png` (default value) or `webp`. input_fidelity: Control how much effort the model will exert to match the style and features, especially facial features, of input images. This parameter is only supported for `gpt-image-1` and `gpt-image-1.5` and later models, unsupported for `gpt-image-1-mini`. Supports `high` and `low`. Defaults to `low`. mask: An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where `image` should be edited. If there are multiple images provided, the mask will be applied on the first image. Must be a valid PNG file, less than 4MB, and have the same dimensions as `image`. model: The model to use for image generation. Defaults to `gpt-image-1.5`. n: The number of images to generate. Must be between 1 and 10. output_compression: The compression level (0-100%) for the generated images. This parameter is only supported for the GPT image models with the `webp` or `jpeg` output formats, and defaults to 100. output_format: The format in which the generated images are returned. This parameter is only supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`. The default value is `png`. partial_images: The number of partial images to generate. This parameter is used for streaming responses that return partial images. Value must be between 0 and 3. When set to 0, the response will be a single image sent in one streaming event. Note that the final image may be sent before the full number of partial images are generated if the full image is generated more quickly. quality: The quality of the image that will be generated for GPT image models. Defaults to `auto`. response_format: The format in which the generated images are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. This parameter is only supported for `dall-e-2` (default is `url` for `dall-e-2`), as GPT image models always return base64-encoded images. size: The size of the generated images. Must be one of `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto` (default value) for the GPT image models, and one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`. stream: Edit the image in streaming mode. Defaults to `false`. See the [Image generation guide](https://platform.openai.com/docs/guides/image-generation) for more information. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload async def edit( self, *, image: Union[FileTypes, SequenceNotStr[FileTypes]], prompt: str, stream: Literal[True], background: Optional[Literal["transparent", "opaque", "auto"]] | Omit = omit, input_fidelity: Optional[Literal["high", "low"]] | Omit = omit, mask: FileTypes | Omit = omit, model: Union[str, ImageModel, None] | Omit = omit, n: Optional[int] | Omit = omit, output_compression: Optional[int] | Omit = omit, output_format: Optional[Literal["png", "jpeg", "webp"]] | Omit = omit, partial_images: Optional[int] | Omit = omit, quality: Optional[Literal["standard", "low", "medium", "high", "auto"]] | Omit = omit, response_format: Optional[Literal["url", "b64_json"]] | Omit = omit, size: Optional[Literal["256x256", "512x512", "1024x1024", "1536x1024", "1024x1536", "auto"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncStream[ImageEditStreamEvent]: """Creates an edited or extended image given one or more source images and a prompt. This endpoint supports GPT Image models (`gpt-image-1.5`, `gpt-image-1`, `gpt-image-1-mini`, and `chatgpt-image-latest`) and `dall-e-2`. Args: image: The image(s) to edit. Must be a supported image file or an array of images. For the GPT image models (`gpt-image-1`, `gpt-image-1-mini`, and `gpt-image-1.5`), each image should be a `png`, `webp`, or `jpg` file less than 50MB. You can provide up to 16 images. `chatgpt-image-latest` follows the same input constraints as GPT image models. For `dall-e-2`, you can only provide one image, and it should be a square `png` file less than 4MB. prompt: A text description of the desired image(s). The maximum length is 1000 characters for `dall-e-2`, and 32000 characters for the GPT image models. stream: Edit the image in streaming mode. Defaults to `false`. See the [Image generation guide](https://platform.openai.com/docs/guides/image-generation) for more information. background: Allows to set transparency for the background of the generated image(s). This parameter is only supported for the GPT image models. Must be one of `transparent`, `opaque` or `auto` (default value). When `auto` is used, the model will automatically determine the best background for the image. If `transparent`, the output format needs to support transparency, so it should be set to either `png` (default value) or `webp`. input_fidelity: Control how much effort the model will exert to match the style and features, especially facial features, of input images. This parameter is only supported for `gpt-image-1` and `gpt-image-1.5` and later models, unsupported for `gpt-image-1-mini`. Supports `high` and `low`. Defaults to `low`. mask: An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where `image` should be edited. If there are multiple images provided, the mask will be applied on the first image. Must be a valid PNG file, less than 4MB, and have the same dimensions as `image`. model: The model to use for image generation. Defaults to `gpt-image-1.5`. n: The number of images to generate. Must be between 1 and 10. output_compression: The compression level (0-100%) for the generated images. This parameter is only supported for the GPT image models with the `webp` or `jpeg` output formats, and defaults to 100. output_format: The format in which the generated images are returned. This parameter is only supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`. The default value is `png`. partial_images: The number of partial images to generate. This parameter is used for streaming responses that return partial images. Value must be between 0 and 3. When set to 0, the response will be a single image sent in one streaming event. Note that the final image may be sent before the full number of partial images are generated if the full image is generated more quickly. quality: The quality of the image that will be generated for GPT image models. Defaults to `auto`. response_format: The format in which the generated images are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. This parameter is only supported for `dall-e-2` (default is `url` for `dall-e-2`), as GPT image models always return base64-encoded images. size: The size of the generated images. Must be one of `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto` (default value) for the GPT image models, and one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload async def edit( self, *, image: Union[FileTypes, SequenceNotStr[FileTypes]], prompt: str, stream: bool, background: Optional[Literal["transparent", "opaque", "auto"]] | Omit = omit, input_fidelity: Optional[Literal["high", "low"]] | Omit = omit, mask: FileTypes | Omit = omit, model: Union[str, ImageModel, None] | Omit = omit, n: Optional[int] | Omit = omit, output_compression: Optional[int] | Omit = omit, output_format: Optional[Literal["png", "jpeg", "webp"]] | Omit = omit, partial_images: Optional[int] | Omit = omit, quality: Optional[Literal["standard", "low", "medium", "high", "auto"]] | Omit = omit, response_format: Optional[Literal["url", "b64_json"]] | Omit = omit, size: Optional[Literal["256x256", "512x512", "1024x1024", "1536x1024", "1024x1536", "auto"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ImagesResponse | AsyncStream[ImageEditStreamEvent]: """Creates an edited or extended image given one or more source images and a prompt. This endpoint supports GPT Image models (`gpt-image-1.5`, `gpt-image-1`, `gpt-image-1-mini`, and `chatgpt-image-latest`) and `dall-e-2`. Args: image: The image(s) to edit. Must be a supported image file or an array of images. For the GPT image models (`gpt-image-1`, `gpt-image-1-mini`, and `gpt-image-1.5`), each image should be a `png`, `webp`, or `jpg` file less than 50MB. You can provide up to 16 images. `chatgpt-image-latest` follows the same input constraints as GPT image models. For `dall-e-2`, you can only provide one image, and it should be a square `png` file less than 4MB. prompt: A text description of the desired image(s). The maximum length is 1000 characters for `dall-e-2`, and 32000 characters for the GPT image models. stream: Edit the image in streaming mode. Defaults to `false`. See the [Image generation guide](https://platform.openai.com/docs/guides/image-generation) for more information. background: Allows to set transparency for the background of the generated image(s). This parameter is only supported for the GPT image models. Must be one of `transparent`, `opaque` or `auto` (default value). When `auto` is used, the model will automatically determine the best background for the image. If `transparent`, the output format needs to support transparency, so it should be set to either `png` (default value) or `webp`. input_fidelity: Control how much effort the model will exert to match the style and features, especially facial features, of input images. This parameter is only supported for `gpt-image-1` and `gpt-image-1.5` and later models, unsupported for `gpt-image-1-mini`. Supports `high` and `low`. Defaults to `low`. mask: An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where `image` should be edited. If there are multiple images provided, the mask will be applied on the first image. Must be a valid PNG file, less than 4MB, and have the same dimensions as `image`. model: The model to use for image generation. Defaults to `gpt-image-1.5`. n: The number of images to generate. Must be between 1 and 10. output_compression: The compression level (0-100%) for the generated images. This parameter is only supported for the GPT image models with the `webp` or `jpeg` output formats, and defaults to 100. output_format: The format in which the generated images are returned. This parameter is only supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`. The default value is `png`. partial_images: The number of partial images to generate. This parameter is used for streaming responses that return partial images. Value must be between 0 and 3. When set to 0, the response will be a single image sent in one streaming event. Note that the final image may be sent before the full number of partial images are generated if the full image is generated more quickly. quality: The quality of the image that will be generated for GPT image models. Defaults to `auto`. response_format: The format in which the generated images are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. This parameter is only supported for `dall-e-2` (default is `url` for `dall-e-2`), as GPT image models always return base64-encoded images. size: The size of the generated images. Must be one of `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto` (default value) for the GPT image models, and one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @required_args(["image", "prompt"], ["image", "prompt", "stream"]) async def edit( self, *, image: Union[FileTypes, SequenceNotStr[FileTypes]], prompt: str, background: Optional[Literal["transparent", "opaque", "auto"]] | Omit = omit, input_fidelity: Optional[Literal["high", "low"]] | Omit = omit, mask: FileTypes | Omit = omit, model: Union[str, ImageModel, None] | Omit = omit, n: Optional[int] | Omit = omit, output_compression: Optional[int] | Omit = omit, output_format: Optional[Literal["png", "jpeg", "webp"]] | Omit = omit, partial_images: Optional[int] | Omit = omit, quality: Optional[Literal["standard", "low", "medium", "high", "auto"]] | Omit = omit, response_format: Optional[Literal["url", "b64_json"]] | Omit = omit, size: Optional[Literal["256x256", "512x512", "1024x1024", "1536x1024", "1024x1536", "auto"]] | Omit = omit, stream: Optional[Literal[False]] | Literal[True] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ImagesResponse | AsyncStream[ImageEditStreamEvent]: body = deepcopy_minimal( { "image": image, "prompt": prompt, "background": background, "input_fidelity": input_fidelity, "mask": mask, "model": model, "n": n, "output_compression": output_compression, "output_format": output_format, "partial_images": partial_images, "quality": quality, "response_format": response_format, "size": size, "stream": stream, "user": user, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["image"], ["image", ""], ["mask"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return await self._post( "/images/edits", body=await async_maybe_transform( body, image_edit_params.ImageEditParamsStreaming if stream else image_edit_params.ImageEditParamsNonStreaming, ), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ImagesResponse, stream=stream or False, stream_cls=AsyncStream[ImageEditStreamEvent], ) @overload async def generate( self, *, prompt: str, background: Optional[Literal["transparent", "opaque", "auto"]] | Omit = omit, model: Union[str, ImageModel, None] | Omit = omit, moderation: Optional[Literal["low", "auto"]] | Omit = omit, n: Optional[int] | Omit = omit, output_compression: Optional[int] | Omit = omit, output_format: Optional[Literal["png", "jpeg", "webp"]] | Omit = omit, partial_images: Optional[int] | Omit = omit, quality: Optional[Literal["standard", "hd", "low", "medium", "high", "auto"]] | Omit = omit, response_format: Optional[Literal["url", "b64_json"]] | Omit = omit, size: Optional[ Literal["auto", "1024x1024", "1536x1024", "1024x1536", "256x256", "512x512", "1792x1024", "1024x1792"] ] | Omit = omit, stream: Optional[Literal[False]] | Omit = omit, style: Optional[Literal["vivid", "natural"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ImagesResponse: """ Creates an image given a prompt. [Learn more](https://platform.openai.com/docs/guides/images). Args: prompt: A text description of the desired image(s). The maximum length is 32000 characters for the GPT image models, 1000 characters for `dall-e-2` and 4000 characters for `dall-e-3`. background: Allows to set transparency for the background of the generated image(s). This parameter is only supported for the GPT image models. Must be one of `transparent`, `opaque` or `auto` (default value). When `auto` is used, the model will automatically determine the best background for the image. If `transparent`, the output format needs to support transparency, so it should be set to either `png` (default value) or `webp`. model: The model to use for image generation. One of `dall-e-2`, `dall-e-3`, or a GPT image model (`gpt-image-1`, `gpt-image-1-mini`, `gpt-image-1.5`). Defaults to `dall-e-2` unless a parameter specific to the GPT image models is used. moderation: Control the content-moderation level for images generated by the GPT image models. Must be either `low` for less restrictive filtering or `auto` (default value). n: The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is supported. output_compression: The compression level (0-100%) for the generated images. This parameter is only supported for the GPT image models with the `webp` or `jpeg` output formats, and defaults to 100. output_format: The format in which the generated images are returned. This parameter is only supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`. partial_images: The number of partial images to generate. This parameter is used for streaming responses that return partial images. Value must be between 0 and 3. When set to 0, the response will be a single image sent in one streaming event. Note that the final image may be sent before the full number of partial images are generated if the full image is generated more quickly. quality: The quality of the image that will be generated. - `auto` (default value) will automatically select the best quality for the given model. - `high`, `medium` and `low` are supported for the GPT image models. - `hd` and `standard` are supported for `dall-e-3`. - `standard` is the only option for `dall-e-2`. response_format: The format in which generated images with `dall-e-2` and `dall-e-3` are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. This parameter isn't supported for the GPT image models, which always return base64-encoded images. size: The size of the generated images. Must be one of `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto` (default value) for the GPT image models, one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`, and one of `1024x1024`, `1792x1024`, or `1024x1792` for `dall-e-3`. stream: Generate the image in streaming mode. Defaults to `false`. See the [Image generation guide](https://platform.openai.com/docs/guides/image-generation) for more information. This parameter is only supported for the GPT image models. style: The style of the generated images. This parameter is only supported for `dall-e-3`. Must be one of `vivid` or `natural`. Vivid causes the model to lean towards generating hyper-real and dramatic images. Natural causes the model to produce more natural, less hyper-real looking images. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload async def generate( self, *, prompt: str, stream: Literal[True], background: Optional[Literal["transparent", "opaque", "auto"]] | Omit = omit, model: Union[str, ImageModel, None] | Omit = omit, moderation: Optional[Literal["low", "auto"]] | Omit = omit, n: Optional[int] | Omit = omit, output_compression: Optional[int] | Omit = omit, output_format: Optional[Literal["png", "jpeg", "webp"]] | Omit = omit, partial_images: Optional[int] | Omit = omit, quality: Optional[Literal["standard", "hd", "low", "medium", "high", "auto"]] | Omit = omit, response_format: Optional[Literal["url", "b64_json"]] | Omit = omit, size: Optional[ Literal["auto", "1024x1024", "1536x1024", "1024x1536", "256x256", "512x512", "1792x1024", "1024x1792"] ] | Omit = omit, style: Optional[Literal["vivid", "natural"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncStream[ImageGenStreamEvent]: """ Creates an image given a prompt. [Learn more](https://platform.openai.com/docs/guides/images). Args: prompt: A text description of the desired image(s). The maximum length is 32000 characters for the GPT image models, 1000 characters for `dall-e-2` and 4000 characters for `dall-e-3`. stream: Generate the image in streaming mode. Defaults to `false`. See the [Image generation guide](https://platform.openai.com/docs/guides/image-generation) for more information. This parameter is only supported for the GPT image models. background: Allows to set transparency for the background of the generated image(s). This parameter is only supported for the GPT image models. Must be one of `transparent`, `opaque` or `auto` (default value). When `auto` is used, the model will automatically determine the best background for the image. If `transparent`, the output format needs to support transparency, so it should be set to either `png` (default value) or `webp`. model: The model to use for image generation. One of `dall-e-2`, `dall-e-3`, or a GPT image model (`gpt-image-1`, `gpt-image-1-mini`, `gpt-image-1.5`). Defaults to `dall-e-2` unless a parameter specific to the GPT image models is used. moderation: Control the content-moderation level for images generated by the GPT image models. Must be either `low` for less restrictive filtering or `auto` (default value). n: The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is supported. output_compression: The compression level (0-100%) for the generated images. This parameter is only supported for the GPT image models with the `webp` or `jpeg` output formats, and defaults to 100. output_format: The format in which the generated images are returned. This parameter is only supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`. partial_images: The number of partial images to generate. This parameter is used for streaming responses that return partial images. Value must be between 0 and 3. When set to 0, the response will be a single image sent in one streaming event. Note that the final image may be sent before the full number of partial images are generated if the full image is generated more quickly. quality: The quality of the image that will be generated. - `auto` (default value) will automatically select the best quality for the given model. - `high`, `medium` and `low` are supported for the GPT image models. - `hd` and `standard` are supported for `dall-e-3`. - `standard` is the only option for `dall-e-2`. response_format: The format in which generated images with `dall-e-2` and `dall-e-3` are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. This parameter isn't supported for the GPT image models, which always return base64-encoded images. size: The size of the generated images. Must be one of `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto` (default value) for the GPT image models, one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`, and one of `1024x1024`, `1792x1024`, or `1024x1792` for `dall-e-3`. style: The style of the generated images. This parameter is only supported for `dall-e-3`. Must be one of `vivid` or `natural`. Vivid causes the model to lean towards generating hyper-real and dramatic images. Natural causes the model to produce more natural, less hyper-real looking images. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload async def generate( self, *, prompt: str, stream: bool, background: Optional[Literal["transparent", "opaque", "auto"]] | Omit = omit, model: Union[str, ImageModel, None] | Omit = omit, moderation: Optional[Literal["low", "auto"]] | Omit = omit, n: Optional[int] | Omit = omit, output_compression: Optional[int] | Omit = omit, output_format: Optional[Literal["png", "jpeg", "webp"]] | Omit = omit, partial_images: Optional[int] | Omit = omit, quality: Optional[Literal["standard", "hd", "low", "medium", "high", "auto"]] | Omit = omit, response_format: Optional[Literal["url", "b64_json"]] | Omit = omit, size: Optional[ Literal["auto", "1024x1024", "1536x1024", "1024x1536", "256x256", "512x512", "1792x1024", "1024x1792"] ] | Omit = omit, style: Optional[Literal["vivid", "natural"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ImagesResponse | AsyncStream[ImageGenStreamEvent]: """ Creates an image given a prompt. [Learn more](https://platform.openai.com/docs/guides/images). Args: prompt: A text description of the desired image(s). The maximum length is 32000 characters for the GPT image models, 1000 characters for `dall-e-2` and 4000 characters for `dall-e-3`. stream: Generate the image in streaming mode. Defaults to `false`. See the [Image generation guide](https://platform.openai.com/docs/guides/image-generation) for more information. This parameter is only supported for the GPT image models. background: Allows to set transparency for the background of the generated image(s). This parameter is only supported for the GPT image models. Must be one of `transparent`, `opaque` or `auto` (default value). When `auto` is used, the model will automatically determine the best background for the image. If `transparent`, the output format needs to support transparency, so it should be set to either `png` (default value) or `webp`. model: The model to use for image generation. One of `dall-e-2`, `dall-e-3`, or a GPT image model (`gpt-image-1`, `gpt-image-1-mini`, `gpt-image-1.5`). Defaults to `dall-e-2` unless a parameter specific to the GPT image models is used. moderation: Control the content-moderation level for images generated by the GPT image models. Must be either `low` for less restrictive filtering or `auto` (default value). n: The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is supported. output_compression: The compression level (0-100%) for the generated images. This parameter is only supported for the GPT image models with the `webp` or `jpeg` output formats, and defaults to 100. output_format: The format in which the generated images are returned. This parameter is only supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`. partial_images: The number of partial images to generate. This parameter is used for streaming responses that return partial images. Value must be between 0 and 3. When set to 0, the response will be a single image sent in one streaming event. Note that the final image may be sent before the full number of partial images are generated if the full image is generated more quickly. quality: The quality of the image that will be generated. - `auto` (default value) will automatically select the best quality for the given model. - `high`, `medium` and `low` are supported for the GPT image models. - `hd` and `standard` are supported for `dall-e-3`. - `standard` is the only option for `dall-e-2`. response_format: The format in which generated images with `dall-e-2` and `dall-e-3` are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. This parameter isn't supported for the GPT image models, which always return base64-encoded images. size: The size of the generated images. Must be one of `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto` (default value) for the GPT image models, one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`, and one of `1024x1024`, `1792x1024`, or `1024x1792` for `dall-e-3`. style: The style of the generated images. This parameter is only supported for `dall-e-3`. Must be one of `vivid` or `natural`. Vivid causes the model to lean towards generating hyper-real and dramatic images. Natural causes the model to produce more natural, less hyper-real looking images. user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @required_args(["prompt"], ["prompt", "stream"]) async def generate( self, *, prompt: str, background: Optional[Literal["transparent", "opaque", "auto"]] | Omit = omit, model: Union[str, ImageModel, None] | Omit = omit, moderation: Optional[Literal["low", "auto"]] | Omit = omit, n: Optional[int] | Omit = omit, output_compression: Optional[int] | Omit = omit, output_format: Optional[Literal["png", "jpeg", "webp"]] | Omit = omit, partial_images: Optional[int] | Omit = omit, quality: Optional[Literal["standard", "hd", "low", "medium", "high", "auto"]] | Omit = omit, response_format: Optional[Literal["url", "b64_json"]] | Omit = omit, size: Optional[ Literal["auto", "1024x1024", "1536x1024", "1024x1536", "256x256", "512x512", "1792x1024", "1024x1792"] ] | Omit = omit, stream: Optional[Literal[False]] | Literal[True] | Omit = omit, style: Optional[Literal["vivid", "natural"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ImagesResponse | AsyncStream[ImageGenStreamEvent]: return await self._post( "/images/generations", body=await async_maybe_transform( { "prompt": prompt, "background": background, "model": model, "moderation": moderation, "n": n, "output_compression": output_compression, "output_format": output_format, "partial_images": partial_images, "quality": quality, "response_format": response_format, "size": size, "stream": stream, "style": style, "user": user, }, image_generate_params.ImageGenerateParamsStreaming if stream else image_generate_params.ImageGenerateParamsNonStreaming, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ImagesResponse, stream=stream or False, stream_cls=AsyncStream[ImageGenStreamEvent], ) class ImagesWithRawResponse: def __init__(self, images: Images) -> None: self._images = images self.create_variation = _legacy_response.to_raw_response_wrapper( images.create_variation, ) self.edit = _legacy_response.to_raw_response_wrapper( images.edit, ) self.generate = _legacy_response.to_raw_response_wrapper( images.generate, ) class AsyncImagesWithRawResponse: def __init__(self, images: AsyncImages) -> None: self._images = images self.create_variation = _legacy_response.async_to_raw_response_wrapper( images.create_variation, ) self.edit = _legacy_response.async_to_raw_response_wrapper( images.edit, ) self.generate = _legacy_response.async_to_raw_response_wrapper( images.generate, ) class ImagesWithStreamingResponse: def __init__(self, images: Images) -> None: self._images = images self.create_variation = to_streamed_response_wrapper( images.create_variation, ) self.edit = to_streamed_response_wrapper( images.edit, ) self.generate = to_streamed_response_wrapper( images.generate, ) class AsyncImagesWithStreamingResponse: def __init__(self, images: AsyncImages) -> None: self._images = images self.create_variation = async_to_streamed_response_wrapper( images.create_variation, ) self.edit = async_to_streamed_response_wrapper( images.edit, ) self.generate = async_to_streamed_response_wrapper( images.generate, ) ================================================ FILE: src/openai/resources/models.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import httpx from .. import _legacy_response from .._types import Body, Query, Headers, NotGiven, not_given from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ..pagination import SyncPage, AsyncPage from ..types.model import Model from .._base_client import ( AsyncPaginator, make_request_options, ) from ..types.model_deleted import ModelDeleted __all__ = ["Models", "AsyncModels"] class Models(SyncAPIResource): """List and describe the various models available in the API.""" @cached_property def with_raw_response(self) -> ModelsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return ModelsWithRawResponse(self) @cached_property def with_streaming_response(self) -> ModelsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return ModelsWithStreamingResponse(self) def retrieve( self, model: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Model: """ Retrieves a model instance, providing basic information about the model such as the owner and permissioning. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not model: raise ValueError(f"Expected a non-empty value for `model` but received {model!r}") return self._get( f"/models/{model}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Model, ) def list( self, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[Model]: """ Lists the currently available models, and provides basic information about each one such as the owner and availability. """ return self._get_api_list( "/models", page=SyncPage[Model], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), model=Model, ) def delete( self, model: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ModelDeleted: """Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not model: raise ValueError(f"Expected a non-empty value for `model` but received {model!r}") return self._delete( f"/models/{model}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ModelDeleted, ) class AsyncModels(AsyncAPIResource): """List and describe the various models available in the API.""" @cached_property def with_raw_response(self) -> AsyncModelsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncModelsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncModelsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncModelsWithStreamingResponse(self) async def retrieve( self, model: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Model: """ Retrieves a model instance, providing basic information about the model such as the owner and permissioning. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not model: raise ValueError(f"Expected a non-empty value for `model` but received {model!r}") return await self._get( f"/models/{model}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Model, ) def list( self, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[Model, AsyncPage[Model]]: """ Lists the currently available models, and provides basic information about each one such as the owner and availability. """ return self._get_api_list( "/models", page=AsyncPage[Model], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), model=Model, ) async def delete( self, model: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ModelDeleted: """Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not model: raise ValueError(f"Expected a non-empty value for `model` but received {model!r}") return await self._delete( f"/models/{model}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ModelDeleted, ) class ModelsWithRawResponse: def __init__(self, models: Models) -> None: self._models = models self.retrieve = _legacy_response.to_raw_response_wrapper( models.retrieve, ) self.list = _legacy_response.to_raw_response_wrapper( models.list, ) self.delete = _legacy_response.to_raw_response_wrapper( models.delete, ) class AsyncModelsWithRawResponse: def __init__(self, models: AsyncModels) -> None: self._models = models self.retrieve = _legacy_response.async_to_raw_response_wrapper( models.retrieve, ) self.list = _legacy_response.async_to_raw_response_wrapper( models.list, ) self.delete = _legacy_response.async_to_raw_response_wrapper( models.delete, ) class ModelsWithStreamingResponse: def __init__(self, models: Models) -> None: self._models = models self.retrieve = to_streamed_response_wrapper( models.retrieve, ) self.list = to_streamed_response_wrapper( models.list, ) self.delete = to_streamed_response_wrapper( models.delete, ) class AsyncModelsWithStreamingResponse: def __init__(self, models: AsyncModels) -> None: self._models = models self.retrieve = async_to_streamed_response_wrapper( models.retrieve, ) self.list = async_to_streamed_response_wrapper( models.list, ) self.delete = async_to_streamed_response_wrapper( models.delete, ) ================================================ FILE: src/openai/resources/moderations.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable import httpx from .. import _legacy_response from ..types import moderation_create_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from .._base_client import make_request_options from ..types.moderation_model import ModerationModel from ..types.moderation_create_response import ModerationCreateResponse from ..types.moderation_multi_modal_input_param import ModerationMultiModalInputParam __all__ = ["Moderations", "AsyncModerations"] class Moderations(SyncAPIResource): """ Given text and/or image inputs, classifies if those inputs are potentially harmful. """ @cached_property def with_raw_response(self) -> ModerationsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return ModerationsWithRawResponse(self) @cached_property def with_streaming_response(self) -> ModerationsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return ModerationsWithStreamingResponse(self) def create( self, *, input: Union[str, SequenceNotStr[str], Iterable[ModerationMultiModalInputParam]], model: Union[str, ModerationModel] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ModerationCreateResponse: """Classifies if text and/or image inputs are potentially harmful. Learn more in the [moderation guide](https://platform.openai.com/docs/guides/moderation). Args: input: Input (or inputs) to classify. Can be a single string, an array of strings, or an array of multi-modal input objects similar to other models. model: The content moderation model you would like to use. Learn more in [the moderation guide](https://platform.openai.com/docs/guides/moderation), and learn about available models [here](https://platform.openai.com/docs/models#moderation). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._post( "/moderations", body=maybe_transform( { "input": input, "model": model, }, moderation_create_params.ModerationCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ModerationCreateResponse, ) class AsyncModerations(AsyncAPIResource): """ Given text and/or image inputs, classifies if those inputs are potentially harmful. """ @cached_property def with_raw_response(self) -> AsyncModerationsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncModerationsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncModerationsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncModerationsWithStreamingResponse(self) async def create( self, *, input: Union[str, SequenceNotStr[str], Iterable[ModerationMultiModalInputParam]], model: Union[str, ModerationModel] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ModerationCreateResponse: """Classifies if text and/or image inputs are potentially harmful. Learn more in the [moderation guide](https://platform.openai.com/docs/guides/moderation). Args: input: Input (or inputs) to classify. Can be a single string, an array of strings, or an array of multi-modal input objects similar to other models. model: The content moderation model you would like to use. Learn more in [the moderation guide](https://platform.openai.com/docs/guides/moderation), and learn about available models [here](https://platform.openai.com/docs/models#moderation). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return await self._post( "/moderations", body=await async_maybe_transform( { "input": input, "model": model, }, moderation_create_params.ModerationCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ModerationCreateResponse, ) class ModerationsWithRawResponse: def __init__(self, moderations: Moderations) -> None: self._moderations = moderations self.create = _legacy_response.to_raw_response_wrapper( moderations.create, ) class AsyncModerationsWithRawResponse: def __init__(self, moderations: AsyncModerations) -> None: self._moderations = moderations self.create = _legacy_response.async_to_raw_response_wrapper( moderations.create, ) class ModerationsWithStreamingResponse: def __init__(self, moderations: Moderations) -> None: self._moderations = moderations self.create = to_streamed_response_wrapper( moderations.create, ) class AsyncModerationsWithStreamingResponse: def __init__(self, moderations: AsyncModerations) -> None: self._moderations = moderations self.create = async_to_streamed_response_wrapper( moderations.create, ) ================================================ FILE: src/openai/resources/realtime/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .calls import ( Calls, AsyncCalls, CallsWithRawResponse, AsyncCallsWithRawResponse, CallsWithStreamingResponse, AsyncCallsWithStreamingResponse, ) from .realtime import ( Realtime, AsyncRealtime, RealtimeWithRawResponse, AsyncRealtimeWithRawResponse, RealtimeWithStreamingResponse, AsyncRealtimeWithStreamingResponse, ) from .client_secrets import ( ClientSecrets, AsyncClientSecrets, ClientSecretsWithRawResponse, AsyncClientSecretsWithRawResponse, ClientSecretsWithStreamingResponse, AsyncClientSecretsWithStreamingResponse, ) __all__ = [ "ClientSecrets", "AsyncClientSecrets", "ClientSecretsWithRawResponse", "AsyncClientSecretsWithRawResponse", "ClientSecretsWithStreamingResponse", "AsyncClientSecretsWithStreamingResponse", "Calls", "AsyncCalls", "CallsWithRawResponse", "AsyncCallsWithRawResponse", "CallsWithStreamingResponse", "AsyncCallsWithStreamingResponse", "Realtime", "AsyncRealtime", "RealtimeWithRawResponse", "AsyncRealtimeWithRawResponse", "RealtimeWithStreamingResponse", "AsyncRealtimeWithStreamingResponse", ] ================================================ FILE: src/openai/resources/realtime/api.md ================================================ # Realtime Types: ```python from openai.types.realtime import ( AudioTranscription, ConversationCreatedEvent, ConversationItem, ConversationItemAdded, ConversationItemCreateEvent, ConversationItemCreatedEvent, ConversationItemDeleteEvent, ConversationItemDeletedEvent, ConversationItemDone, ConversationItemInputAudioTranscriptionCompletedEvent, ConversationItemInputAudioTranscriptionDeltaEvent, ConversationItemInputAudioTranscriptionFailedEvent, ConversationItemInputAudioTranscriptionSegment, ConversationItemRetrieveEvent, ConversationItemTruncateEvent, ConversationItemTruncatedEvent, ConversationItemWithReference, InputAudioBufferAppendEvent, InputAudioBufferClearEvent, InputAudioBufferClearedEvent, InputAudioBufferCommitEvent, InputAudioBufferCommittedEvent, InputAudioBufferDtmfEventReceivedEvent, InputAudioBufferSpeechStartedEvent, InputAudioBufferSpeechStoppedEvent, InputAudioBufferTimeoutTriggered, LogProbProperties, McpListToolsCompleted, McpListToolsFailed, McpListToolsInProgress, NoiseReductionType, OutputAudioBufferClearEvent, RateLimitsUpdatedEvent, RealtimeAudioConfig, RealtimeAudioConfigInput, RealtimeAudioConfigOutput, RealtimeAudioFormats, RealtimeAudioInputTurnDetection, RealtimeClientEvent, RealtimeConversationItemAssistantMessage, RealtimeConversationItemFunctionCall, RealtimeConversationItemFunctionCallOutput, RealtimeConversationItemSystemMessage, RealtimeConversationItemUserMessage, RealtimeError, RealtimeErrorEvent, RealtimeFunctionTool, RealtimeMcpApprovalRequest, RealtimeMcpApprovalResponse, RealtimeMcpListTools, RealtimeMcpProtocolError, RealtimeMcpToolCall, RealtimeMcpToolExecutionError, RealtimeMcphttpError, RealtimeResponse, RealtimeResponseCreateAudioOutput, RealtimeResponseCreateMcpTool, RealtimeResponseCreateParams, RealtimeResponseStatus, RealtimeResponseUsage, RealtimeResponseUsageInputTokenDetails, RealtimeResponseUsageOutputTokenDetails, RealtimeServerEvent, RealtimeSession, RealtimeSessionCreateRequest, RealtimeToolChoiceConfig, RealtimeToolsConfig, RealtimeToolsConfigUnion, RealtimeTracingConfig, RealtimeTranscriptionSessionAudio, RealtimeTranscriptionSessionAudioInput, RealtimeTranscriptionSessionAudioInputTurnDetection, RealtimeTranscriptionSessionCreateRequest, RealtimeTruncation, RealtimeTruncationRetentionRatio, ResponseAudioDeltaEvent, ResponseAudioDoneEvent, ResponseAudioTranscriptDeltaEvent, ResponseAudioTranscriptDoneEvent, ResponseCancelEvent, ResponseContentPartAddedEvent, ResponseContentPartDoneEvent, ResponseCreateEvent, ResponseCreatedEvent, ResponseDoneEvent, ResponseFunctionCallArgumentsDeltaEvent, ResponseFunctionCallArgumentsDoneEvent, ResponseMcpCallArgumentsDelta, ResponseMcpCallArgumentsDone, ResponseMcpCallCompleted, ResponseMcpCallFailed, ResponseMcpCallInProgress, ResponseOutputItemAddedEvent, ResponseOutputItemDoneEvent, ResponseTextDeltaEvent, ResponseTextDoneEvent, SessionCreatedEvent, SessionUpdateEvent, SessionUpdatedEvent, TranscriptionSessionUpdate, TranscriptionSessionUpdatedEvent, ) ``` ## ClientSecrets Types: ```python from openai.types.realtime import ( RealtimeSessionClientSecret, RealtimeSessionCreateResponse, RealtimeTranscriptionSessionCreateResponse, RealtimeTranscriptionSessionTurnDetection, ClientSecretCreateResponse, ) ``` Methods: - client.realtime.client_secrets.create(\*\*params) -> ClientSecretCreateResponse ## Calls Methods: - client.realtime.calls.create(\*\*params) -> HttpxBinaryResponseContent - client.realtime.calls.accept(call_id, \*\*params) -> None - client.realtime.calls.hangup(call_id) -> None - client.realtime.calls.refer(call_id, \*\*params) -> None - client.realtime.calls.reject(call_id, \*\*params) -> None ================================================ FILE: src/openai/resources/realtime/calls.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List, Union, Optional from typing_extensions import Literal import httpx from ... import _legacy_response from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( StreamedBinaryAPIResponse, AsyncStreamedBinaryAPIResponse, to_streamed_response_wrapper, async_to_streamed_response_wrapper, to_custom_streamed_response_wrapper, async_to_custom_streamed_response_wrapper, ) from ..._base_client import make_request_options from ...types.realtime import ( call_refer_params, call_accept_params, call_create_params, call_reject_params, ) from ...types.responses.response_prompt_param import ResponsePromptParam from ...types.realtime.realtime_truncation_param import RealtimeTruncationParam from ...types.realtime.realtime_audio_config_param import RealtimeAudioConfigParam from ...types.realtime.realtime_tools_config_param import RealtimeToolsConfigParam from ...types.realtime.realtime_tracing_config_param import RealtimeTracingConfigParam from ...types.realtime.realtime_tool_choice_config_param import RealtimeToolChoiceConfigParam from ...types.realtime.realtime_session_create_request_param import RealtimeSessionCreateRequestParam __all__ = ["Calls", "AsyncCalls"] class Calls(SyncAPIResource): @cached_property def with_raw_response(self) -> CallsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return CallsWithRawResponse(self) @cached_property def with_streaming_response(self) -> CallsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return CallsWithStreamingResponse(self) def create( self, *, sdp: str, session: RealtimeSessionCreateRequestParam | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: """ Create a new Realtime API call over WebRTC and receive the SDP answer needed to complete the peer connection. Args: sdp: WebRTC Session Description Protocol (SDP) offer generated by the caller. session: Realtime session object configuration. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"Accept": "application/sdp", **(extra_headers or {})} return self._post( "/realtime/calls", body=maybe_transform( { "sdp": sdp, "session": session, }, call_create_params.CallCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=_legacy_response.HttpxBinaryResponseContent, ) def accept( self, call_id: str, *, type: Literal["realtime"], audio: RealtimeAudioConfigParam | Omit = omit, include: List[Literal["item.input_audio_transcription.logprobs"]] | Omit = omit, instructions: str | Omit = omit, max_output_tokens: Union[int, Literal["inf"]] | Omit = omit, model: Union[ str, Literal[ "gpt-realtime", "gpt-realtime-1.5", "gpt-realtime-2025-08-28", "gpt-4o-realtime-preview", "gpt-4o-realtime-preview-2024-10-01", "gpt-4o-realtime-preview-2024-12-17", "gpt-4o-realtime-preview-2025-06-03", "gpt-4o-mini-realtime-preview", "gpt-4o-mini-realtime-preview-2024-12-17", "gpt-realtime-mini", "gpt-realtime-mini-2025-10-06", "gpt-realtime-mini-2025-12-15", "gpt-audio-1.5", "gpt-audio-mini", "gpt-audio-mini-2025-10-06", "gpt-audio-mini-2025-12-15", ], ] | Omit = omit, output_modalities: List[Literal["text", "audio"]] | Omit = omit, prompt: Optional[ResponsePromptParam] | Omit = omit, tool_choice: RealtimeToolChoiceConfigParam | Omit = omit, tools: RealtimeToolsConfigParam | Omit = omit, tracing: Optional[RealtimeTracingConfigParam] | Omit = omit, truncation: RealtimeTruncationParam | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Accept an incoming SIP call and configure the realtime session that will handle it. Args: type: The type of session to create. Always `realtime` for the Realtime API. audio: Configuration for input and output audio. include: Additional fields to include in server outputs. `item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription. instructions: The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. "be extremely succinct", "act friendly", "here are examples of good responses") and on audio behavior (e.g. "talk quickly", "inject emotion into your voice", "laugh frequently"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior. Note that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session. max_output_tokens: Maximum number of output tokens for a single assistant response, inclusive of tool calls. Provide an integer between 1 and 4096 to limit output tokens, or `inf` for the maximum available tokens for a given model. Defaults to `inf`. model: The Realtime model used for this session. output_modalities: The set of modalities the model can respond with. It defaults to `["audio"]`, indicating that the model will respond with audio plus a transcript. `["text"]` can be used to make the model respond with text only. It is not possible to request both `text` and `audio` at the same time. prompt: Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). tool_choice: How the model chooses tools. Provide one of the string modes or force a specific function/MCP tool. tools: Tools available to the model. tracing: Realtime API can write session traces to the [Traces Dashboard](/logs?api=traces). Set to null to disable tracing. Once tracing is enabled for a session, the configuration cannot be modified. `auto` will create a trace for the session with default values for the workflow name, group id, and metadata. truncation: When the number of tokens in a conversation exceeds the model's input token limit, the conversation be truncated, meaning messages (starting from the oldest) will not be included in the model's context. A 32k context model with 4,096 max output tokens can only include 28,224 tokens in the context before truncation occurs. Clients can configure truncation behavior to truncate with a lower max token limit, which is an effective way to control token usage and cost. Truncation will reduce the number of cached tokens on the next turn (busting the cache), since messages are dropped from the beginning of the context. However, clients can also configure truncation to retain messages up to a fraction of the maximum context size, which will reduce the need for future truncations and thus improve the cache rate. Truncation can be disabled entirely, which means the server will never truncate but would instead return an error if the conversation exceeds the model's input token limit. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not call_id: raise ValueError(f"Expected a non-empty value for `call_id` but received {call_id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._post( f"/realtime/calls/{call_id}/accept", body=maybe_transform( { "type": type, "audio": audio, "include": include, "instructions": instructions, "max_output_tokens": max_output_tokens, "model": model, "output_modalities": output_modalities, "prompt": prompt, "tool_choice": tool_choice, "tools": tools, "tracing": tracing, "truncation": truncation, }, call_accept_params.CallAcceptParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=NoneType, ) def hangup( self, call_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ End an active Realtime API call, whether it was initiated over SIP or WebRTC. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not call_id: raise ValueError(f"Expected a non-empty value for `call_id` but received {call_id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._post( f"/realtime/calls/{call_id}/hangup", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=NoneType, ) def refer( self, call_id: str, *, target_uri: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Transfer an active SIP call to a new destination using the SIP REFER verb. Args: target_uri: URI that should appear in the SIP Refer-To header. Supports values like `tel:+14155550123` or `sip:agent@example.com`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not call_id: raise ValueError(f"Expected a non-empty value for `call_id` but received {call_id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._post( f"/realtime/calls/{call_id}/refer", body=maybe_transform({"target_uri": target_uri}, call_refer_params.CallReferParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=NoneType, ) def reject( self, call_id: str, *, status_code: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Decline an incoming SIP call by returning a SIP status code to the caller. Args: status_code: SIP response code to send back to the caller. Defaults to `603` (Decline) when omitted. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not call_id: raise ValueError(f"Expected a non-empty value for `call_id` but received {call_id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._post( f"/realtime/calls/{call_id}/reject", body=maybe_transform({"status_code": status_code}, call_reject_params.CallRejectParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=NoneType, ) class AsyncCalls(AsyncAPIResource): @cached_property def with_raw_response(self) -> AsyncCallsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncCallsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncCallsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncCallsWithStreamingResponse(self) async def create( self, *, sdp: str, session: RealtimeSessionCreateRequestParam | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: """ Create a new Realtime API call over WebRTC and receive the SDP answer needed to complete the peer connection. Args: sdp: WebRTC Session Description Protocol (SDP) offer generated by the caller. session: Realtime session object configuration. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"Accept": "application/sdp", **(extra_headers or {})} return await self._post( "/realtime/calls", body=await async_maybe_transform( { "sdp": sdp, "session": session, }, call_create_params.CallCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=_legacy_response.HttpxBinaryResponseContent, ) async def accept( self, call_id: str, *, type: Literal["realtime"], audio: RealtimeAudioConfigParam | Omit = omit, include: List[Literal["item.input_audio_transcription.logprobs"]] | Omit = omit, instructions: str | Omit = omit, max_output_tokens: Union[int, Literal["inf"]] | Omit = omit, model: Union[ str, Literal[ "gpt-realtime", "gpt-realtime-1.5", "gpt-realtime-2025-08-28", "gpt-4o-realtime-preview", "gpt-4o-realtime-preview-2024-10-01", "gpt-4o-realtime-preview-2024-12-17", "gpt-4o-realtime-preview-2025-06-03", "gpt-4o-mini-realtime-preview", "gpt-4o-mini-realtime-preview-2024-12-17", "gpt-realtime-mini", "gpt-realtime-mini-2025-10-06", "gpt-realtime-mini-2025-12-15", "gpt-audio-1.5", "gpt-audio-mini", "gpt-audio-mini-2025-10-06", "gpt-audio-mini-2025-12-15", ], ] | Omit = omit, output_modalities: List[Literal["text", "audio"]] | Omit = omit, prompt: Optional[ResponsePromptParam] | Omit = omit, tool_choice: RealtimeToolChoiceConfigParam | Omit = omit, tools: RealtimeToolsConfigParam | Omit = omit, tracing: Optional[RealtimeTracingConfigParam] | Omit = omit, truncation: RealtimeTruncationParam | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Accept an incoming SIP call and configure the realtime session that will handle it. Args: type: The type of session to create. Always `realtime` for the Realtime API. audio: Configuration for input and output audio. include: Additional fields to include in server outputs. `item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription. instructions: The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. "be extremely succinct", "act friendly", "here are examples of good responses") and on audio behavior (e.g. "talk quickly", "inject emotion into your voice", "laugh frequently"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior. Note that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session. max_output_tokens: Maximum number of output tokens for a single assistant response, inclusive of tool calls. Provide an integer between 1 and 4096 to limit output tokens, or `inf` for the maximum available tokens for a given model. Defaults to `inf`. model: The Realtime model used for this session. output_modalities: The set of modalities the model can respond with. It defaults to `["audio"]`, indicating that the model will respond with audio plus a transcript. `["text"]` can be used to make the model respond with text only. It is not possible to request both `text` and `audio` at the same time. prompt: Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). tool_choice: How the model chooses tools. Provide one of the string modes or force a specific function/MCP tool. tools: Tools available to the model. tracing: Realtime API can write session traces to the [Traces Dashboard](/logs?api=traces). Set to null to disable tracing. Once tracing is enabled for a session, the configuration cannot be modified. `auto` will create a trace for the session with default values for the workflow name, group id, and metadata. truncation: When the number of tokens in a conversation exceeds the model's input token limit, the conversation be truncated, meaning messages (starting from the oldest) will not be included in the model's context. A 32k context model with 4,096 max output tokens can only include 28,224 tokens in the context before truncation occurs. Clients can configure truncation behavior to truncate with a lower max token limit, which is an effective way to control token usage and cost. Truncation will reduce the number of cached tokens on the next turn (busting the cache), since messages are dropped from the beginning of the context. However, clients can also configure truncation to retain messages up to a fraction of the maximum context size, which will reduce the need for future truncations and thus improve the cache rate. Truncation can be disabled entirely, which means the server will never truncate but would instead return an error if the conversation exceeds the model's input token limit. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not call_id: raise ValueError(f"Expected a non-empty value for `call_id` but received {call_id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._post( f"/realtime/calls/{call_id}/accept", body=await async_maybe_transform( { "type": type, "audio": audio, "include": include, "instructions": instructions, "max_output_tokens": max_output_tokens, "model": model, "output_modalities": output_modalities, "prompt": prompt, "tool_choice": tool_choice, "tools": tools, "tracing": tracing, "truncation": truncation, }, call_accept_params.CallAcceptParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=NoneType, ) async def hangup( self, call_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ End an active Realtime API call, whether it was initiated over SIP or WebRTC. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not call_id: raise ValueError(f"Expected a non-empty value for `call_id` but received {call_id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._post( f"/realtime/calls/{call_id}/hangup", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=NoneType, ) async def refer( self, call_id: str, *, target_uri: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Transfer an active SIP call to a new destination using the SIP REFER verb. Args: target_uri: URI that should appear in the SIP Refer-To header. Supports values like `tel:+14155550123` or `sip:agent@example.com`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not call_id: raise ValueError(f"Expected a non-empty value for `call_id` but received {call_id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._post( f"/realtime/calls/{call_id}/refer", body=await async_maybe_transform({"target_uri": target_uri}, call_refer_params.CallReferParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=NoneType, ) async def reject( self, call_id: str, *, status_code: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Decline an incoming SIP call by returning a SIP status code to the caller. Args: status_code: SIP response code to send back to the caller. Defaults to `603` (Decline) when omitted. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not call_id: raise ValueError(f"Expected a non-empty value for `call_id` but received {call_id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._post( f"/realtime/calls/{call_id}/reject", body=await async_maybe_transform({"status_code": status_code}, call_reject_params.CallRejectParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=NoneType, ) class CallsWithRawResponse: def __init__(self, calls: Calls) -> None: self._calls = calls self.create = _legacy_response.to_raw_response_wrapper( calls.create, ) self.accept = _legacy_response.to_raw_response_wrapper( calls.accept, ) self.hangup = _legacy_response.to_raw_response_wrapper( calls.hangup, ) self.refer = _legacy_response.to_raw_response_wrapper( calls.refer, ) self.reject = _legacy_response.to_raw_response_wrapper( calls.reject, ) class AsyncCallsWithRawResponse: def __init__(self, calls: AsyncCalls) -> None: self._calls = calls self.create = _legacy_response.async_to_raw_response_wrapper( calls.create, ) self.accept = _legacy_response.async_to_raw_response_wrapper( calls.accept, ) self.hangup = _legacy_response.async_to_raw_response_wrapper( calls.hangup, ) self.refer = _legacy_response.async_to_raw_response_wrapper( calls.refer, ) self.reject = _legacy_response.async_to_raw_response_wrapper( calls.reject, ) class CallsWithStreamingResponse: def __init__(self, calls: Calls) -> None: self._calls = calls self.create = to_custom_streamed_response_wrapper( calls.create, StreamedBinaryAPIResponse, ) self.accept = to_streamed_response_wrapper( calls.accept, ) self.hangup = to_streamed_response_wrapper( calls.hangup, ) self.refer = to_streamed_response_wrapper( calls.refer, ) self.reject = to_streamed_response_wrapper( calls.reject, ) class AsyncCallsWithStreamingResponse: def __init__(self, calls: AsyncCalls) -> None: self._calls = calls self.create = async_to_custom_streamed_response_wrapper( calls.create, AsyncStreamedBinaryAPIResponse, ) self.accept = async_to_streamed_response_wrapper( calls.accept, ) self.hangup = async_to_streamed_response_wrapper( calls.hangup, ) self.refer = async_to_streamed_response_wrapper( calls.refer, ) self.reject = async_to_streamed_response_wrapper( calls.reject, ) ================================================ FILE: src/openai/resources/realtime/client_secrets.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import httpx from ... import _legacy_response from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ..._base_client import make_request_options from ...types.realtime import client_secret_create_params from ...types.realtime.client_secret_create_response import ClientSecretCreateResponse __all__ = ["ClientSecrets", "AsyncClientSecrets"] class ClientSecrets(SyncAPIResource): @cached_property def with_raw_response(self) -> ClientSecretsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return ClientSecretsWithRawResponse(self) @cached_property def with_streaming_response(self) -> ClientSecretsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return ClientSecretsWithStreamingResponse(self) def create( self, *, expires_after: client_secret_create_params.ExpiresAfter | Omit = omit, session: client_secret_create_params.Session | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ClientSecretCreateResponse: """ Create a Realtime client secret with an associated session configuration. Client secrets are short-lived tokens that can be passed to a client app, such as a web frontend or mobile client, which grants access to the Realtime API without leaking your main API key. You can configure a custom TTL for each client secret. You can also attach session configuration options to the client secret, which will be applied to any sessions created using that client secret, but these can also be overridden by the client connection. [Learn more about authentication with client secrets over WebRTC](https://platform.openai.com/docs/guides/realtime-webrtc). Returns the created client secret and the effective session object. The client secret is a string that looks like `ek_1234`. Args: expires_after: Configuration for the client secret expiration. Expiration refers to the time after which a client secret will no longer be valid for creating sessions. The session itself may continue after that time once started. A secret can be used to create multiple sessions until it expires. session: Session configuration to use for the client secret. Choose either a realtime session or a transcription session. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._post( "/realtime/client_secrets", body=maybe_transform( { "expires_after": expires_after, "session": session, }, client_secret_create_params.ClientSecretCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ClientSecretCreateResponse, ) class AsyncClientSecrets(AsyncAPIResource): @cached_property def with_raw_response(self) -> AsyncClientSecretsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncClientSecretsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncClientSecretsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncClientSecretsWithStreamingResponse(self) async def create( self, *, expires_after: client_secret_create_params.ExpiresAfter | Omit = omit, session: client_secret_create_params.Session | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ClientSecretCreateResponse: """ Create a Realtime client secret with an associated session configuration. Client secrets are short-lived tokens that can be passed to a client app, such as a web frontend or mobile client, which grants access to the Realtime API without leaking your main API key. You can configure a custom TTL for each client secret. You can also attach session configuration options to the client secret, which will be applied to any sessions created using that client secret, but these can also be overridden by the client connection. [Learn more about authentication with client secrets over WebRTC](https://platform.openai.com/docs/guides/realtime-webrtc). Returns the created client secret and the effective session object. The client secret is a string that looks like `ek_1234`. Args: expires_after: Configuration for the client secret expiration. Expiration refers to the time after which a client secret will no longer be valid for creating sessions. The session itself may continue after that time once started. A secret can be used to create multiple sessions until it expires. session: Session configuration to use for the client secret. Choose either a realtime session or a transcription session. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return await self._post( "/realtime/client_secrets", body=await async_maybe_transform( { "expires_after": expires_after, "session": session, }, client_secret_create_params.ClientSecretCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ClientSecretCreateResponse, ) class ClientSecretsWithRawResponse: def __init__(self, client_secrets: ClientSecrets) -> None: self._client_secrets = client_secrets self.create = _legacy_response.to_raw_response_wrapper( client_secrets.create, ) class AsyncClientSecretsWithRawResponse: def __init__(self, client_secrets: AsyncClientSecrets) -> None: self._client_secrets = client_secrets self.create = _legacy_response.async_to_raw_response_wrapper( client_secrets.create, ) class ClientSecretsWithStreamingResponse: def __init__(self, client_secrets: ClientSecrets) -> None: self._client_secrets = client_secrets self.create = to_streamed_response_wrapper( client_secrets.create, ) class AsyncClientSecretsWithStreamingResponse: def __init__(self, client_secrets: AsyncClientSecrets) -> None: self._client_secrets = client_secrets self.create = async_to_streamed_response_wrapper( client_secrets.create, ) ================================================ FILE: src/openai/resources/realtime/realtime.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import json import logging from types import TracebackType from typing import TYPE_CHECKING, Any, Iterator, cast from typing_extensions import AsyncIterator import httpx from pydantic import BaseModel from .calls import ( Calls, AsyncCalls, CallsWithRawResponse, AsyncCallsWithRawResponse, CallsWithStreamingResponse, AsyncCallsWithStreamingResponse, ) from ..._types import Omit, Query, Headers, omit from ..._utils import ( is_azure_client, maybe_transform, strip_not_given, async_maybe_transform, is_async_azure_client, ) from ..._compat import cached_property from ..._models import construct_type_unchecked from ..._resource import SyncAPIResource, AsyncAPIResource from ..._exceptions import OpenAIError from ..._base_client import _merge_mappings from .client_secrets import ( ClientSecrets, AsyncClientSecrets, ClientSecretsWithRawResponse, AsyncClientSecretsWithRawResponse, ClientSecretsWithStreamingResponse, AsyncClientSecretsWithStreamingResponse, ) from ...types.realtime import session_update_event_param from ...types.websocket_connection_options import WebSocketConnectionOptions from ...types.realtime.realtime_client_event import RealtimeClientEvent from ...types.realtime.realtime_server_event import RealtimeServerEvent from ...types.realtime.conversation_item_param import ConversationItemParam from ...types.realtime.realtime_client_event_param import RealtimeClientEventParam from ...types.realtime.realtime_response_create_params_param import RealtimeResponseCreateParamsParam if TYPE_CHECKING: from websockets.sync.client import ClientConnection as WebSocketConnection from websockets.asyncio.client import ClientConnection as AsyncWebSocketConnection from ..._client import OpenAI, AsyncOpenAI __all__ = ["Realtime", "AsyncRealtime"] log: logging.Logger = logging.getLogger(__name__) class Realtime(SyncAPIResource): @cached_property def client_secrets(self) -> ClientSecrets: return ClientSecrets(self._client) @cached_property def calls(self) -> Calls: from ...lib._realtime import _Calls return _Calls(self._client) @cached_property def with_raw_response(self) -> RealtimeWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return RealtimeWithRawResponse(self) @cached_property def with_streaming_response(self) -> RealtimeWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return RealtimeWithStreamingResponse(self) def connect( self, *, call_id: str | Omit = omit, model: str | Omit = omit, extra_query: Query = {}, extra_headers: Headers = {}, websocket_connection_options: WebSocketConnectionOptions = {}, ) -> RealtimeConnectionManager: """ The Realtime API enables you to build low-latency, multi-modal conversational experiences. It currently supports text and audio as both input and output, as well as function calling. Some notable benefits of the API include: - Native speech-to-speech: Skipping an intermediate text format means low latency and nuanced output. - Natural, steerable voices: The models have natural inflection and can laugh, whisper, and adhere to tone direction. - Simultaneous multimodal output: Text is useful for moderation; faster-than-realtime audio ensures stable playback. The Realtime API is a stateful, event-based API that communicates over a WebSocket. """ return RealtimeConnectionManager( client=self._client, extra_query=extra_query, extra_headers=extra_headers, websocket_connection_options=websocket_connection_options, call_id=call_id, model=model, ) class AsyncRealtime(AsyncAPIResource): @cached_property def client_secrets(self) -> AsyncClientSecrets: return AsyncClientSecrets(self._client) @cached_property def calls(self) -> AsyncCalls: from ...lib._realtime import _AsyncCalls return _AsyncCalls(self._client) @cached_property def with_raw_response(self) -> AsyncRealtimeWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncRealtimeWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncRealtimeWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncRealtimeWithStreamingResponse(self) def connect( self, *, call_id: str | Omit = omit, model: str | Omit = omit, extra_query: Query = {}, extra_headers: Headers = {}, websocket_connection_options: WebSocketConnectionOptions = {}, ) -> AsyncRealtimeConnectionManager: """ The Realtime API enables you to build low-latency, multi-modal conversational experiences. It currently supports text and audio as both input and output, as well as function calling. Some notable benefits of the API include: - Native speech-to-speech: Skipping an intermediate text format means low latency and nuanced output. - Natural, steerable voices: The models have natural inflection and can laugh, whisper, and adhere to tone direction. - Simultaneous multimodal output: Text is useful for moderation; faster-than-realtime audio ensures stable playback. The Realtime API is a stateful, event-based API that communicates over a WebSocket. """ return AsyncRealtimeConnectionManager( client=self._client, extra_query=extra_query, extra_headers=extra_headers, websocket_connection_options=websocket_connection_options, call_id=call_id, model=model, ) class RealtimeWithRawResponse: def __init__(self, realtime: Realtime) -> None: self._realtime = realtime @cached_property def client_secrets(self) -> ClientSecretsWithRawResponse: return ClientSecretsWithRawResponse(self._realtime.client_secrets) @cached_property def calls(self) -> CallsWithRawResponse: return CallsWithRawResponse(self._realtime.calls) class AsyncRealtimeWithRawResponse: def __init__(self, realtime: AsyncRealtime) -> None: self._realtime = realtime @cached_property def client_secrets(self) -> AsyncClientSecretsWithRawResponse: return AsyncClientSecretsWithRawResponse(self._realtime.client_secrets) @cached_property def calls(self) -> AsyncCallsWithRawResponse: return AsyncCallsWithRawResponse(self._realtime.calls) class RealtimeWithStreamingResponse: def __init__(self, realtime: Realtime) -> None: self._realtime = realtime @cached_property def client_secrets(self) -> ClientSecretsWithStreamingResponse: return ClientSecretsWithStreamingResponse(self._realtime.client_secrets) @cached_property def calls(self) -> CallsWithStreamingResponse: return CallsWithStreamingResponse(self._realtime.calls) class AsyncRealtimeWithStreamingResponse: def __init__(self, realtime: AsyncRealtime) -> None: self._realtime = realtime @cached_property def client_secrets(self) -> AsyncClientSecretsWithStreamingResponse: return AsyncClientSecretsWithStreamingResponse(self._realtime.client_secrets) @cached_property def calls(self) -> AsyncCallsWithStreamingResponse: return AsyncCallsWithStreamingResponse(self._realtime.calls) class AsyncRealtimeConnection: """Represents a live WebSocket connection to the Realtime API""" session: AsyncRealtimeSessionResource response: AsyncRealtimeResponseResource input_audio_buffer: AsyncRealtimeInputAudioBufferResource conversation: AsyncRealtimeConversationResource output_audio_buffer: AsyncRealtimeOutputAudioBufferResource _connection: AsyncWebSocketConnection def __init__(self, connection: AsyncWebSocketConnection) -> None: self._connection = connection self.session = AsyncRealtimeSessionResource(self) self.response = AsyncRealtimeResponseResource(self) self.input_audio_buffer = AsyncRealtimeInputAudioBufferResource(self) self.conversation = AsyncRealtimeConversationResource(self) self.output_audio_buffer = AsyncRealtimeOutputAudioBufferResource(self) async def __aiter__(self) -> AsyncIterator[RealtimeServerEvent]: """ An infinite-iterator that will continue to yield events until the connection is closed. """ from websockets.exceptions import ConnectionClosedOK try: while True: yield await self.recv() except ConnectionClosedOK: return async def recv(self) -> RealtimeServerEvent: """ Receive the next message from the connection and parses it into a `RealtimeServerEvent` object. Canceling this method is safe. There's no risk of losing data. """ return self.parse_event(await self.recv_bytes()) async def recv_bytes(self) -> bytes: """Receive the next message from the connection as raw bytes. Canceling this method is safe. There's no risk of losing data. If you want to parse the message into a `RealtimeServerEvent` object like `.recv()` does, then you can call `.parse_event(data)`. """ message = await self._connection.recv(decode=False) log.debug(f"Received WebSocket message: %s", message) return message async def send(self, event: RealtimeClientEvent | RealtimeClientEventParam) -> None: data = ( event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) if isinstance(event, BaseModel) else json.dumps(await async_maybe_transform(event, RealtimeClientEventParam)) ) await self._connection.send(data) async def close(self, *, code: int = 1000, reason: str = "") -> None: await self._connection.close(code=code, reason=reason) def parse_event(self, data: str | bytes) -> RealtimeServerEvent: """ Converts a raw `str` or `bytes` message into a `RealtimeServerEvent` object. This is helpful if you're using `.recv_bytes()`. """ return cast( RealtimeServerEvent, construct_type_unchecked(value=json.loads(data), type_=cast(Any, RealtimeServerEvent)) ) class AsyncRealtimeConnectionManager: """ Context manager over a `AsyncRealtimeConnection` that is returned by `realtime.connect()` This context manager ensures that the connection will be closed when it exits. --- Note that if your application doesn't work well with the context manager approach then you can call the `.enter()` method directly to initiate a connection. **Warning**: You must remember to close the connection with `.close()`. ```py connection = await client.realtime.connect(...).enter() # ... await connection.close() ``` """ def __init__( self, *, client: AsyncOpenAI, call_id: str | Omit = omit, model: str | Omit = omit, extra_query: Query, extra_headers: Headers, websocket_connection_options: WebSocketConnectionOptions, ) -> None: self.__client = client self.__call_id = call_id self.__model = model self.__connection: AsyncRealtimeConnection | None = None self.__extra_query = extra_query self.__extra_headers = extra_headers self.__websocket_connection_options = websocket_connection_options async def __aenter__(self) -> AsyncRealtimeConnection: """ 👋 If your application doesn't work well with the context manager approach then you can call this method directly to initiate a connection. **Warning**: You must remember to close the connection with `.close()`. ```py connection = await client.realtime.connect(...).enter() # ... await connection.close() ``` """ try: from websockets.asyncio.client import connect except ImportError as exc: raise OpenAIError("You need to install `openai[realtime]` to use this method") from exc extra_query = self.__extra_query await self.__client._refresh_api_key() auth_headers = self.__client.auth_headers extra_query = self.__extra_query if self.__call_id is not omit: extra_query = {**extra_query, "call_id": self.__call_id} if is_async_azure_client(self.__client): model = self.__model if not model: raise OpenAIError("`model` is required for Azure Realtime API") else: url, auth_headers = await self.__client._configure_realtime(model, extra_query) else: url = self._prepare_url().copy_with( params={ **self.__client.base_url.params, **({"model": self.__model} if self.__model is not omit else {}), **extra_query, }, ) log.debug("Connecting to %s", url) if self.__websocket_connection_options: log.debug("Connection options: %s", self.__websocket_connection_options) self.__connection = AsyncRealtimeConnection( await connect( str(url), user_agent_header=self.__client.user_agent, additional_headers=_merge_mappings( { **auth_headers, }, self.__extra_headers, ), **self.__websocket_connection_options, ) ) return self.__connection enter = __aenter__ def _prepare_url(self) -> httpx.URL: if self.__client.websocket_base_url is not None: base_url = httpx.URL(self.__client.websocket_base_url) else: scheme = self.__client._base_url.scheme ws_scheme = "ws" if scheme == "http" else "wss" base_url = self.__client._base_url.copy_with(scheme=ws_scheme) merge_raw_path = base_url.raw_path.rstrip(b"/") + b"/realtime" return base_url.copy_with(raw_path=merge_raw_path) async def __aexit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None ) -> None: if self.__connection is not None: await self.__connection.close() class RealtimeConnection: """Represents a live WebSocket connection to the Realtime API""" session: RealtimeSessionResource response: RealtimeResponseResource input_audio_buffer: RealtimeInputAudioBufferResource conversation: RealtimeConversationResource output_audio_buffer: RealtimeOutputAudioBufferResource _connection: WebSocketConnection def __init__(self, connection: WebSocketConnection) -> None: self._connection = connection self.session = RealtimeSessionResource(self) self.response = RealtimeResponseResource(self) self.input_audio_buffer = RealtimeInputAudioBufferResource(self) self.conversation = RealtimeConversationResource(self) self.output_audio_buffer = RealtimeOutputAudioBufferResource(self) def __iter__(self) -> Iterator[RealtimeServerEvent]: """ An infinite-iterator that will continue to yield events until the connection is closed. """ from websockets.exceptions import ConnectionClosedOK try: while True: yield self.recv() except ConnectionClosedOK: return def recv(self) -> RealtimeServerEvent: """ Receive the next message from the connection and parses it into a `RealtimeServerEvent` object. Canceling this method is safe. There's no risk of losing data. """ return self.parse_event(self.recv_bytes()) def recv_bytes(self) -> bytes: """Receive the next message from the connection as raw bytes. Canceling this method is safe. There's no risk of losing data. If you want to parse the message into a `RealtimeServerEvent` object like `.recv()` does, then you can call `.parse_event(data)`. """ message = self._connection.recv(decode=False) log.debug(f"Received WebSocket message: %s", message) return message def send(self, event: RealtimeClientEvent | RealtimeClientEventParam) -> None: data = ( event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) if isinstance(event, BaseModel) else json.dumps(maybe_transform(event, RealtimeClientEventParam)) ) self._connection.send(data) def close(self, *, code: int = 1000, reason: str = "") -> None: self._connection.close(code=code, reason=reason) def parse_event(self, data: str | bytes) -> RealtimeServerEvent: """ Converts a raw `str` or `bytes` message into a `RealtimeServerEvent` object. This is helpful if you're using `.recv_bytes()`. """ return cast( RealtimeServerEvent, construct_type_unchecked(value=json.loads(data), type_=cast(Any, RealtimeServerEvent)) ) class RealtimeConnectionManager: """ Context manager over a `RealtimeConnection` that is returned by `realtime.connect()` This context manager ensures that the connection will be closed when it exits. --- Note that if your application doesn't work well with the context manager approach then you can call the `.enter()` method directly to initiate a connection. **Warning**: You must remember to close the connection with `.close()`. ```py connection = client.realtime.connect(...).enter() # ... connection.close() ``` """ def __init__( self, *, client: OpenAI, call_id: str | Omit = omit, model: str | Omit = omit, extra_query: Query, extra_headers: Headers, websocket_connection_options: WebSocketConnectionOptions, ) -> None: self.__client = client self.__call_id = call_id self.__model = model self.__connection: RealtimeConnection | None = None self.__extra_query = extra_query self.__extra_headers = extra_headers self.__websocket_connection_options = websocket_connection_options def __enter__(self) -> RealtimeConnection: """ 👋 If your application doesn't work well with the context manager approach then you can call this method directly to initiate a connection. **Warning**: You must remember to close the connection with `.close()`. ```py connection = client.realtime.connect(...).enter() # ... connection.close() ``` """ try: from websockets.sync.client import connect except ImportError as exc: raise OpenAIError("You need to install `openai[realtime]` to use this method") from exc extra_query = self.__extra_query self.__client._refresh_api_key() auth_headers = self.__client.auth_headers extra_query = self.__extra_query if self.__call_id is not omit: extra_query = {**extra_query, "call_id": self.__call_id} if is_azure_client(self.__client): model = self.__model if not model: raise OpenAIError("`model` is required for Azure Realtime API") else: url, auth_headers = self.__client._configure_realtime(model, extra_query) else: url = self._prepare_url().copy_with( params={ **self.__client.base_url.params, **({"model": self.__model} if self.__model is not omit else {}), **extra_query, }, ) log.debug("Connecting to %s", url) if self.__websocket_connection_options: log.debug("Connection options: %s", self.__websocket_connection_options) self.__connection = RealtimeConnection( connect( str(url), user_agent_header=self.__client.user_agent, additional_headers=_merge_mappings( { **auth_headers, }, self.__extra_headers, ), **self.__websocket_connection_options, ) ) return self.__connection enter = __enter__ def _prepare_url(self) -> httpx.URL: if self.__client.websocket_base_url is not None: base_url = httpx.URL(self.__client.websocket_base_url) else: scheme = self.__client._base_url.scheme ws_scheme = "ws" if scheme == "http" else "wss" base_url = self.__client._base_url.copy_with(scheme=ws_scheme) merge_raw_path = base_url.raw_path.rstrip(b"/") + b"/realtime" return base_url.copy_with(raw_path=merge_raw_path) def __exit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None ) -> None: if self.__connection is not None: self.__connection.close() class BaseRealtimeConnectionResource: def __init__(self, connection: RealtimeConnection) -> None: self._connection = connection class RealtimeSessionResource(BaseRealtimeConnectionResource): def update(self, *, session: session_update_event_param.Session, event_id: str | Omit = omit) -> None: """ Send this event to update the session’s configuration. The client may send this event at any time to update any field except for `voice` and `model`. `voice` can be updated only if there have been no other audio outputs yet. When the server receives a `session.update`, it will respond with a `session.updated` event showing the full, effective configuration. Only the fields that are present in the `session.update` are updated. To clear a field like `instructions`, pass an empty string. To clear a field like `tools`, pass an empty array. To clear a field like `turn_detection`, pass `null`. """ self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "session.update", "session": session, "event_id": event_id}), ) ) class RealtimeResponseResource(BaseRealtimeConnectionResource): def create(self, *, event_id: str | Omit = omit, response: RealtimeResponseCreateParamsParam | Omit = omit) -> None: """ This event instructs the server to create a Response, which means triggering model inference. When in Server VAD mode, the server will create Responses automatically. A Response will include at least one Item, and may have two, in which case the second will be a function call. These Items will be appended to the conversation history by default. The server will respond with a `response.created` event, events for Items and content created, and finally a `response.done` event to indicate the Response is complete. The `response.create` event includes inference configuration like `instructions` and `tools`. If these are set, they will override the Session's configuration for this Response only. Responses can be created out-of-band of the default Conversation, meaning that they can have arbitrary input, and it's possible to disable writing the output to the Conversation. Only one Response can write to the default Conversation at a time, but otherwise multiple Responses can be created in parallel. The `metadata` field is a good way to disambiguate multiple simultaneous Responses. Clients can set `conversation` to `none` to create a Response that does not write to the default Conversation. Arbitrary input can be provided with the `input` field, which is an array accepting raw Items and references to existing Items. """ self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "response.create", "event_id": event_id, "response": response}), ) ) def cancel(self, *, event_id: str | Omit = omit, response_id: str | Omit = omit) -> None: """Send this event to cancel an in-progress response. The server will respond with a `response.done` event with a status of `response.status=cancelled`. If there is no response to cancel, the server will respond with an error. It's safe to call `response.cancel` even if no response is in progress, an error will be returned the session will remain unaffected. """ self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "response.cancel", "event_id": event_id, "response_id": response_id}), ) ) class RealtimeInputAudioBufferResource(BaseRealtimeConnectionResource): def clear(self, *, event_id: str | Omit = omit) -> None: """Send this event to clear the audio bytes in the buffer. The server will respond with an `input_audio_buffer.cleared` event. """ self._connection.send( cast(RealtimeClientEventParam, strip_not_given({"type": "input_audio_buffer.clear", "event_id": event_id})) ) def commit(self, *, event_id: str | Omit = omit) -> None: """ Send this event to commit the user input audio buffer, which will create a new user message item in the conversation. This event will produce an error if the input audio buffer is empty. When in Server VAD mode, the client does not need to send this event, the server will commit the audio buffer automatically. Committing the input audio buffer will trigger input audio transcription (if enabled in session configuration), but it will not create a response from the model. The server will respond with an `input_audio_buffer.committed` event. """ self._connection.send( cast(RealtimeClientEventParam, strip_not_given({"type": "input_audio_buffer.commit", "event_id": event_id})) ) def append(self, *, audio: str, event_id: str | Omit = omit) -> None: """Send this event to append audio bytes to the input audio buffer. The audio buffer is temporary storage you can write to and later commit. A "commit" will create a new user message item in the conversation history from the buffer content and clear the buffer. Input audio transcription (if enabled) will be generated when the buffer is committed. If VAD is enabled the audio buffer is used to detect speech and the server will decide when to commit. When Server VAD is disabled, you must commit the audio buffer manually. Input audio noise reduction operates on writes to the audio buffer. The client may choose how much audio to place in each event up to a maximum of 15 MiB, for example streaming smaller chunks from the client may allow the VAD to be more responsive. Unlike most other client events, the server will not send a confirmation response to this event. """ self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "input_audio_buffer.append", "audio": audio, "event_id": event_id}), ) ) class RealtimeConversationResource(BaseRealtimeConnectionResource): @cached_property def item(self) -> RealtimeConversationItemResource: return RealtimeConversationItemResource(self._connection) class RealtimeConversationItemResource(BaseRealtimeConnectionResource): def delete(self, *, item_id: str, event_id: str | Omit = omit) -> None: """Send this event when you want to remove any item from the conversation history. The server will respond with a `conversation.item.deleted` event, unless the item does not exist in the conversation history, in which case the server will respond with an error. """ self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "conversation.item.delete", "item_id": item_id, "event_id": event_id}), ) ) def create( self, *, item: ConversationItemParam, event_id: str | Omit = omit, previous_item_id: str | Omit = omit ) -> None: """ Add a new Item to the Conversation's context, including messages, function calls, and function call responses. This event can be used both to populate a "history" of the conversation and to add new items mid-stream, but has the current limitation that it cannot populate assistant audio messages. If successful, the server will respond with a `conversation.item.created` event, otherwise an `error` event will be sent. """ self._connection.send( cast( RealtimeClientEventParam, strip_not_given( { "type": "conversation.item.create", "item": item, "event_id": event_id, "previous_item_id": previous_item_id, } ), ) ) def truncate(self, *, audio_end_ms: int, content_index: int, item_id: str, event_id: str | Omit = omit) -> None: """Send this event to truncate a previous assistant message’s audio. The server will produce audio faster than realtime, so this event is useful when the user interrupts to truncate audio that has already been sent to the client but not yet played. This will synchronize the server's understanding of the audio with the client's playback. Truncating audio will delete the server-side text transcript to ensure there is not text in the context that hasn't been heard by the user. If successful, the server will respond with a `conversation.item.truncated` event. """ self._connection.send( cast( RealtimeClientEventParam, strip_not_given( { "type": "conversation.item.truncate", "audio_end_ms": audio_end_ms, "content_index": content_index, "item_id": item_id, "event_id": event_id, } ), ) ) def retrieve(self, *, item_id: str, event_id: str | Omit = omit) -> None: """ Send this event when you want to retrieve the server's representation of a specific item in the conversation history. This is useful, for example, to inspect user audio after noise cancellation and VAD. The server will respond with a `conversation.item.retrieved` event, unless the item does not exist in the conversation history, in which case the server will respond with an error. """ self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "conversation.item.retrieve", "item_id": item_id, "event_id": event_id}), ) ) class RealtimeOutputAudioBufferResource(BaseRealtimeConnectionResource): def clear(self, *, event_id: str | Omit = omit) -> None: """**WebRTC/SIP Only:** Emit to cut off the current audio response. This will trigger the server to stop generating audio and emit a `output_audio_buffer.cleared` event. This event should be preceded by a `response.cancel` client event to stop the generation of the current response. [Learn more](https://platform.openai.com/docs/guides/realtime-conversations#client-and-server-events-for-audio-in-webrtc). """ self._connection.send( cast(RealtimeClientEventParam, strip_not_given({"type": "output_audio_buffer.clear", "event_id": event_id})) ) class BaseAsyncRealtimeConnectionResource: def __init__(self, connection: AsyncRealtimeConnection) -> None: self._connection = connection class AsyncRealtimeSessionResource(BaseAsyncRealtimeConnectionResource): async def update(self, *, session: session_update_event_param.Session, event_id: str | Omit = omit) -> None: """ Send this event to update the session’s configuration. The client may send this event at any time to update any field except for `voice` and `model`. `voice` can be updated only if there have been no other audio outputs yet. When the server receives a `session.update`, it will respond with a `session.updated` event showing the full, effective configuration. Only the fields that are present in the `session.update` are updated. To clear a field like `instructions`, pass an empty string. To clear a field like `tools`, pass an empty array. To clear a field like `turn_detection`, pass `null`. """ await self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "session.update", "session": session, "event_id": event_id}), ) ) class AsyncRealtimeResponseResource(BaseAsyncRealtimeConnectionResource): async def create( self, *, event_id: str | Omit = omit, response: RealtimeResponseCreateParamsParam | Omit = omit ) -> None: """ This event instructs the server to create a Response, which means triggering model inference. When in Server VAD mode, the server will create Responses automatically. A Response will include at least one Item, and may have two, in which case the second will be a function call. These Items will be appended to the conversation history by default. The server will respond with a `response.created` event, events for Items and content created, and finally a `response.done` event to indicate the Response is complete. The `response.create` event includes inference configuration like `instructions` and `tools`. If these are set, they will override the Session's configuration for this Response only. Responses can be created out-of-band of the default Conversation, meaning that they can have arbitrary input, and it's possible to disable writing the output to the Conversation. Only one Response can write to the default Conversation at a time, but otherwise multiple Responses can be created in parallel. The `metadata` field is a good way to disambiguate multiple simultaneous Responses. Clients can set `conversation` to `none` to create a Response that does not write to the default Conversation. Arbitrary input can be provided with the `input` field, which is an array accepting raw Items and references to existing Items. """ await self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "response.create", "event_id": event_id, "response": response}), ) ) async def cancel(self, *, event_id: str | Omit = omit, response_id: str | Omit = omit) -> None: """Send this event to cancel an in-progress response. The server will respond with a `response.done` event with a status of `response.status=cancelled`. If there is no response to cancel, the server will respond with an error. It's safe to call `response.cancel` even if no response is in progress, an error will be returned the session will remain unaffected. """ await self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "response.cancel", "event_id": event_id, "response_id": response_id}), ) ) class AsyncRealtimeInputAudioBufferResource(BaseAsyncRealtimeConnectionResource): async def clear(self, *, event_id: str | Omit = omit) -> None: """Send this event to clear the audio bytes in the buffer. The server will respond with an `input_audio_buffer.cleared` event. """ await self._connection.send( cast(RealtimeClientEventParam, strip_not_given({"type": "input_audio_buffer.clear", "event_id": event_id})) ) async def commit(self, *, event_id: str | Omit = omit) -> None: """ Send this event to commit the user input audio buffer, which will create a new user message item in the conversation. This event will produce an error if the input audio buffer is empty. When in Server VAD mode, the client does not need to send this event, the server will commit the audio buffer automatically. Committing the input audio buffer will trigger input audio transcription (if enabled in session configuration), but it will not create a response from the model. The server will respond with an `input_audio_buffer.committed` event. """ await self._connection.send( cast(RealtimeClientEventParam, strip_not_given({"type": "input_audio_buffer.commit", "event_id": event_id})) ) async def append(self, *, audio: str, event_id: str | Omit = omit) -> None: """Send this event to append audio bytes to the input audio buffer. The audio buffer is temporary storage you can write to and later commit. A "commit" will create a new user message item in the conversation history from the buffer content and clear the buffer. Input audio transcription (if enabled) will be generated when the buffer is committed. If VAD is enabled the audio buffer is used to detect speech and the server will decide when to commit. When Server VAD is disabled, you must commit the audio buffer manually. Input audio noise reduction operates on writes to the audio buffer. The client may choose how much audio to place in each event up to a maximum of 15 MiB, for example streaming smaller chunks from the client may allow the VAD to be more responsive. Unlike most other client events, the server will not send a confirmation response to this event. """ await self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "input_audio_buffer.append", "audio": audio, "event_id": event_id}), ) ) class AsyncRealtimeConversationResource(BaseAsyncRealtimeConnectionResource): @cached_property def item(self) -> AsyncRealtimeConversationItemResource: return AsyncRealtimeConversationItemResource(self._connection) class AsyncRealtimeConversationItemResource(BaseAsyncRealtimeConnectionResource): async def delete(self, *, item_id: str, event_id: str | Omit = omit) -> None: """Send this event when you want to remove any item from the conversation history. The server will respond with a `conversation.item.deleted` event, unless the item does not exist in the conversation history, in which case the server will respond with an error. """ await self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "conversation.item.delete", "item_id": item_id, "event_id": event_id}), ) ) async def create( self, *, item: ConversationItemParam, event_id: str | Omit = omit, previous_item_id: str | Omit = omit ) -> None: """ Add a new Item to the Conversation's context, including messages, function calls, and function call responses. This event can be used both to populate a "history" of the conversation and to add new items mid-stream, but has the current limitation that it cannot populate assistant audio messages. If successful, the server will respond with a `conversation.item.created` event, otherwise an `error` event will be sent. """ await self._connection.send( cast( RealtimeClientEventParam, strip_not_given( { "type": "conversation.item.create", "item": item, "event_id": event_id, "previous_item_id": previous_item_id, } ), ) ) async def truncate( self, *, audio_end_ms: int, content_index: int, item_id: str, event_id: str | Omit = omit ) -> None: """Send this event to truncate a previous assistant message’s audio. The server will produce audio faster than realtime, so this event is useful when the user interrupts to truncate audio that has already been sent to the client but not yet played. This will synchronize the server's understanding of the audio with the client's playback. Truncating audio will delete the server-side text transcript to ensure there is not text in the context that hasn't been heard by the user. If successful, the server will respond with a `conversation.item.truncated` event. """ await self._connection.send( cast( RealtimeClientEventParam, strip_not_given( { "type": "conversation.item.truncate", "audio_end_ms": audio_end_ms, "content_index": content_index, "item_id": item_id, "event_id": event_id, } ), ) ) async def retrieve(self, *, item_id: str, event_id: str | Omit = omit) -> None: """ Send this event when you want to retrieve the server's representation of a specific item in the conversation history. This is useful, for example, to inspect user audio after noise cancellation and VAD. The server will respond with a `conversation.item.retrieved` event, unless the item does not exist in the conversation history, in which case the server will respond with an error. """ await self._connection.send( cast( RealtimeClientEventParam, strip_not_given({"type": "conversation.item.retrieve", "item_id": item_id, "event_id": event_id}), ) ) class AsyncRealtimeOutputAudioBufferResource(BaseAsyncRealtimeConnectionResource): async def clear(self, *, event_id: str | Omit = omit) -> None: """**WebRTC/SIP Only:** Emit to cut off the current audio response. This will trigger the server to stop generating audio and emit a `output_audio_buffer.cleared` event. This event should be preceded by a `response.cancel` client event to stop the generation of the current response. [Learn more](https://platform.openai.com/docs/guides/realtime-conversations#client-and-server-events-for-audio-in-webrtc). """ await self._connection.send( cast(RealtimeClientEventParam, strip_not_given({"type": "output_audio_buffer.clear", "event_id": event_id})) ) ================================================ FILE: src/openai/resources/responses/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .responses import ( Responses, AsyncResponses, ResponsesWithRawResponse, AsyncResponsesWithRawResponse, ResponsesWithStreamingResponse, AsyncResponsesWithStreamingResponse, ) from .input_items import ( InputItems, AsyncInputItems, InputItemsWithRawResponse, AsyncInputItemsWithRawResponse, InputItemsWithStreamingResponse, AsyncInputItemsWithStreamingResponse, ) from .input_tokens import ( InputTokens, AsyncInputTokens, InputTokensWithRawResponse, AsyncInputTokensWithRawResponse, InputTokensWithStreamingResponse, AsyncInputTokensWithStreamingResponse, ) __all__ = [ "InputItems", "AsyncInputItems", "InputItemsWithRawResponse", "AsyncInputItemsWithRawResponse", "InputItemsWithStreamingResponse", "AsyncInputItemsWithStreamingResponse", "InputTokens", "AsyncInputTokens", "InputTokensWithRawResponse", "AsyncInputTokensWithRawResponse", "InputTokensWithStreamingResponse", "AsyncInputTokensWithStreamingResponse", "Responses", "AsyncResponses", "ResponsesWithRawResponse", "AsyncResponsesWithRawResponse", "ResponsesWithStreamingResponse", "AsyncResponsesWithStreamingResponse", ] ================================================ FILE: src/openai/resources/responses/api.md ================================================ # Responses Types: ```python from openai.types.responses import ( ApplyPatchTool, CompactedResponse, ComputerAction, ComputerActionList, ComputerTool, ComputerUsePreviewTool, ContainerAuto, ContainerNetworkPolicyAllowlist, ContainerNetworkPolicyDisabled, ContainerNetworkPolicyDomainSecret, ContainerReference, CustomTool, EasyInputMessage, FileSearchTool, FunctionShellTool, FunctionTool, InlineSkill, InlineSkillSource, LocalEnvironment, LocalSkill, NamespaceTool, Response, ResponseApplyPatchToolCall, ResponseApplyPatchToolCallOutput, ResponseAudioDeltaEvent, ResponseAudioDoneEvent, ResponseAudioTranscriptDeltaEvent, ResponseAudioTranscriptDoneEvent, ResponseCodeInterpreterCallCodeDeltaEvent, ResponseCodeInterpreterCallCodeDoneEvent, ResponseCodeInterpreterCallCompletedEvent, ResponseCodeInterpreterCallInProgressEvent, ResponseCodeInterpreterCallInterpretingEvent, ResponseCodeInterpreterToolCall, ResponseCompactionItem, ResponseCompactionItemParam, ResponseCompletedEvent, ResponseComputerToolCall, ResponseComputerToolCallOutputItem, ResponseComputerToolCallOutputScreenshot, ResponseContainerReference, ResponseContent, ResponseContentPartAddedEvent, ResponseContentPartDoneEvent, ResponseConversationParam, ResponseCreatedEvent, ResponseCustomToolCall, ResponseCustomToolCallInputDeltaEvent, ResponseCustomToolCallInputDoneEvent, ResponseCustomToolCallOutput, ResponseError, ResponseErrorEvent, ResponseFailedEvent, ResponseFileSearchCallCompletedEvent, ResponseFileSearchCallInProgressEvent, ResponseFileSearchCallSearchingEvent, ResponseFileSearchToolCall, ResponseFormatTextConfig, ResponseFormatTextJSONSchemaConfig, ResponseFunctionCallArgumentsDeltaEvent, ResponseFunctionCallArgumentsDoneEvent, ResponseFunctionCallOutputItem, ResponseFunctionCallOutputItemList, ResponseFunctionShellCallOutputContent, ResponseFunctionShellToolCall, ResponseFunctionShellToolCallOutput, ResponseFunctionToolCall, ResponseFunctionToolCallItem, ResponseFunctionToolCallOutputItem, ResponseFunctionWebSearch, ResponseImageGenCallCompletedEvent, ResponseImageGenCallGeneratingEvent, ResponseImageGenCallInProgressEvent, ResponseImageGenCallPartialImageEvent, ResponseInProgressEvent, ResponseIncludable, ResponseIncompleteEvent, ResponseInput, ResponseInputAudio, ResponseInputContent, ResponseInputFile, ResponseInputFileContent, ResponseInputImage, ResponseInputImageContent, ResponseInputItem, ResponseInputMessageContentList, ResponseInputMessageItem, ResponseInputText, ResponseInputTextContent, ResponseItem, ResponseLocalEnvironment, ResponseMcpCallArgumentsDeltaEvent, ResponseMcpCallArgumentsDoneEvent, ResponseMcpCallCompletedEvent, ResponseMcpCallFailedEvent, ResponseMcpCallInProgressEvent, ResponseMcpListToolsCompletedEvent, ResponseMcpListToolsFailedEvent, ResponseMcpListToolsInProgressEvent, ResponseOutputAudio, ResponseOutputItem, ResponseOutputItemAddedEvent, ResponseOutputItemDoneEvent, ResponseOutputMessage, ResponseOutputRefusal, ResponseOutputText, ResponseOutputTextAnnotationAddedEvent, ResponsePrompt, ResponseQueuedEvent, ResponseReasoningItem, ResponseReasoningSummaryPartAddedEvent, ResponseReasoningSummaryPartDoneEvent, ResponseReasoningSummaryTextDeltaEvent, ResponseReasoningSummaryTextDoneEvent, ResponseReasoningTextDeltaEvent, ResponseReasoningTextDoneEvent, ResponseRefusalDeltaEvent, ResponseRefusalDoneEvent, ResponseStatus, ResponseStreamEvent, ResponseTextConfig, ResponseTextDeltaEvent, ResponseTextDoneEvent, ResponseToolSearchCall, ResponseToolSearchOutputItem, ResponseToolSearchOutputItemParam, ResponseUsage, ResponseWebSearchCallCompletedEvent, ResponseWebSearchCallInProgressEvent, ResponseWebSearchCallSearchingEvent, ResponsesClientEvent, ResponsesServerEvent, SkillReference, Tool, ToolChoiceAllowed, ToolChoiceApplyPatch, ToolChoiceCustom, ToolChoiceFunction, ToolChoiceMcp, ToolChoiceOptions, ToolChoiceShell, ToolChoiceTypes, ToolSearchTool, WebSearchPreviewTool, WebSearchTool, ) ``` Methods: - client.responses.create(\*\*params) -> Response - client.responses.retrieve(response_id, \*\*params) -> Response - client.responses.delete(response_id) -> None - client.responses.cancel(response_id) -> Response - client.responses.compact(\*\*params) -> CompactedResponse ## InputItems Types: ```python from openai.types.responses import ResponseItemList ``` Methods: - client.responses.input_items.list(response_id, \*\*params) -> SyncCursorPage[ResponseItem] ## InputTokens Types: ```python from openai.types.responses import InputTokenCountResponse ``` Methods: - client.responses.input_tokens.count(\*\*params) -> InputTokenCountResponse ================================================ FILE: src/openai/resources/responses/input_items.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Any, List, cast from typing_extensions import Literal import httpx from ... import _legacy_response from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ...pagination import SyncCursorPage, AsyncCursorPage from ..._base_client import AsyncPaginator, make_request_options from ...types.responses import input_item_list_params from ...types.responses.response_item import ResponseItem from ...types.responses.response_includable import ResponseIncludable __all__ = ["InputItems", "AsyncInputItems"] class InputItems(SyncAPIResource): @cached_property def with_raw_response(self) -> InputItemsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return InputItemsWithRawResponse(self) @cached_property def with_streaming_response(self) -> InputItemsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return InputItemsWithStreamingResponse(self) def list( self, response_id: str, *, after: str | Omit = omit, include: List[ResponseIncludable] | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[ResponseItem]: """ Returns a list of input items for a given response. Args: after: An item ID to list items after, used in pagination. include: Additional fields to include in the response. See the `include` parameter for Response creation above for more information. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: The order to return the input items in. Default is `desc`. - `asc`: Return the input items in ascending order. - `desc`: Return the input items in descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not response_id: raise ValueError(f"Expected a non-empty value for `response_id` but received {response_id!r}") return self._get_api_list( f"/responses/{response_id}/input_items", page=SyncCursorPage[ResponseItem], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "include": include, "limit": limit, "order": order, }, input_item_list_params.InputItemListParams, ), ), model=cast(Any, ResponseItem), # Union types cannot be passed in as arguments in the type system ) class AsyncInputItems(AsyncAPIResource): @cached_property def with_raw_response(self) -> AsyncInputItemsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncInputItemsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncInputItemsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncInputItemsWithStreamingResponse(self) def list( self, response_id: str, *, after: str | Omit = omit, include: List[ResponseIncludable] | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[ResponseItem, AsyncCursorPage[ResponseItem]]: """ Returns a list of input items for a given response. Args: after: An item ID to list items after, used in pagination. include: Additional fields to include in the response. See the `include` parameter for Response creation above for more information. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: The order to return the input items in. Default is `desc`. - `asc`: Return the input items in ascending order. - `desc`: Return the input items in descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not response_id: raise ValueError(f"Expected a non-empty value for `response_id` but received {response_id!r}") return self._get_api_list( f"/responses/{response_id}/input_items", page=AsyncCursorPage[ResponseItem], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "include": include, "limit": limit, "order": order, }, input_item_list_params.InputItemListParams, ), ), model=cast(Any, ResponseItem), # Union types cannot be passed in as arguments in the type system ) class InputItemsWithRawResponse: def __init__(self, input_items: InputItems) -> None: self._input_items = input_items self.list = _legacy_response.to_raw_response_wrapper( input_items.list, ) class AsyncInputItemsWithRawResponse: def __init__(self, input_items: AsyncInputItems) -> None: self._input_items = input_items self.list = _legacy_response.async_to_raw_response_wrapper( input_items.list, ) class InputItemsWithStreamingResponse: def __init__(self, input_items: InputItems) -> None: self._input_items = input_items self.list = to_streamed_response_wrapper( input_items.list, ) class AsyncInputItemsWithStreamingResponse: def __init__(self, input_items: AsyncInputItems) -> None: self._input_items = input_items self.list = async_to_streamed_response_wrapper( input_items.list, ) ================================================ FILE: src/openai/resources/responses/input_tokens.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable, Optional from typing_extensions import Literal import httpx from ... import _legacy_response from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ..._base_client import make_request_options from ...types.responses import input_token_count_params from ...types.responses.tool_param import ToolParam from ...types.shared_params.reasoning import Reasoning from ...types.responses.response_input_item_param import ResponseInputItemParam from ...types.responses.input_token_count_response import InputTokenCountResponse __all__ = ["InputTokens", "AsyncInputTokens"] class InputTokens(SyncAPIResource): @cached_property def with_raw_response(self) -> InputTokensWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return InputTokensWithRawResponse(self) @cached_property def with_streaming_response(self) -> InputTokensWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return InputTokensWithStreamingResponse(self) def count( self, *, conversation: Optional[input_token_count_params.Conversation] | Omit = omit, input: Union[str, Iterable[ResponseInputItemParam], None] | Omit = omit, instructions: Optional[str] | Omit = omit, model: Optional[str] | Omit = omit, parallel_tool_calls: Optional[bool] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, reasoning: Optional[Reasoning] | Omit = omit, text: Optional[input_token_count_params.Text] | Omit = omit, tool_choice: Optional[input_token_count_params.ToolChoice] | Omit = omit, tools: Optional[Iterable[ToolParam]] | Omit = omit, truncation: Literal["auto", "disabled"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InputTokenCountResponse: """ Returns input token counts of the request. Returns an object with `object` set to `response.input_tokens` and an `input_tokens` count. Args: conversation: The conversation that this response belongs to. Items from this conversation are prepended to `input_items` for this response request. Input items and output items from this response are automatically added to this conversation after this response completes. input: Text, image, or file inputs to the model, used to generate a response instructions: A system (or developer) message inserted into the model's context. When used along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses. model: Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. parallel_tool_calls: Whether to allow the model to run tool calls in parallel. previous_response_id: The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://platform.openai.com/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`. reasoning: **gpt-5 and o-series models only** Configuration options for [reasoning models](https://platform.openai.com/docs/guides/reasoning). text: Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) tool_choice: Controls which tool the model should use, if any. tools: An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. truncation: The truncation strategy to use for the model response. - `auto`: If the input to this Response exceeds the model's context window size, the model will truncate the response to fit the context window by dropping items from the beginning of the conversation. - `disabled` (default): If the input size will exceed the context window size for a model, the request will fail with a 400 error. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._post( "/responses/input_tokens", body=maybe_transform( { "conversation": conversation, "input": input, "instructions": instructions, "model": model, "parallel_tool_calls": parallel_tool_calls, "previous_response_id": previous_response_id, "reasoning": reasoning, "text": text, "tool_choice": tool_choice, "tools": tools, "truncation": truncation, }, input_token_count_params.InputTokenCountParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=InputTokenCountResponse, ) class AsyncInputTokens(AsyncAPIResource): @cached_property def with_raw_response(self) -> AsyncInputTokensWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncInputTokensWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncInputTokensWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncInputTokensWithStreamingResponse(self) async def count( self, *, conversation: Optional[input_token_count_params.Conversation] | Omit = omit, input: Union[str, Iterable[ResponseInputItemParam], None] | Omit = omit, instructions: Optional[str] | Omit = omit, model: Optional[str] | Omit = omit, parallel_tool_calls: Optional[bool] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, reasoning: Optional[Reasoning] | Omit = omit, text: Optional[input_token_count_params.Text] | Omit = omit, tool_choice: Optional[input_token_count_params.ToolChoice] | Omit = omit, tools: Optional[Iterable[ToolParam]] | Omit = omit, truncation: Literal["auto", "disabled"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InputTokenCountResponse: """ Returns input token counts of the request. Returns an object with `object` set to `response.input_tokens` and an `input_tokens` count. Args: conversation: The conversation that this response belongs to. Items from this conversation are prepended to `input_items` for this response request. Input items and output items from this response are automatically added to this conversation after this response completes. input: Text, image, or file inputs to the model, used to generate a response instructions: A system (or developer) message inserted into the model's context. When used along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses. model: Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. parallel_tool_calls: Whether to allow the model to run tool calls in parallel. previous_response_id: The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://platform.openai.com/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`. reasoning: **gpt-5 and o-series models only** Configuration options for [reasoning models](https://platform.openai.com/docs/guides/reasoning). text: Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) tool_choice: Controls which tool the model should use, if any. tools: An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. truncation: The truncation strategy to use for the model response. - `auto`: If the input to this Response exceeds the model's context window size, the model will truncate the response to fit the context window by dropping items from the beginning of the conversation. - `disabled` (default): If the input size will exceed the context window size for a model, the request will fail with a 400 error. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return await self._post( "/responses/input_tokens", body=await async_maybe_transform( { "conversation": conversation, "input": input, "instructions": instructions, "model": model, "parallel_tool_calls": parallel_tool_calls, "previous_response_id": previous_response_id, "reasoning": reasoning, "text": text, "tool_choice": tool_choice, "tools": tools, "truncation": truncation, }, input_token_count_params.InputTokenCountParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=InputTokenCountResponse, ) class InputTokensWithRawResponse: def __init__(self, input_tokens: InputTokens) -> None: self._input_tokens = input_tokens self.count = _legacy_response.to_raw_response_wrapper( input_tokens.count, ) class AsyncInputTokensWithRawResponse: def __init__(self, input_tokens: AsyncInputTokens) -> None: self._input_tokens = input_tokens self.count = _legacy_response.async_to_raw_response_wrapper( input_tokens.count, ) class InputTokensWithStreamingResponse: def __init__(self, input_tokens: InputTokens) -> None: self._input_tokens = input_tokens self.count = to_streamed_response_wrapper( input_tokens.count, ) class AsyncInputTokensWithStreamingResponse: def __init__(self, input_tokens: AsyncInputTokens) -> None: self._input_tokens = input_tokens self.count = async_to_streamed_response_wrapper( input_tokens.count, ) ================================================ FILE: src/openai/resources/responses/responses.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import json import logging from copy import copy from types import TracebackType from typing import TYPE_CHECKING, Any, List, Type, Union, Iterable, Iterator, Optional, AsyncIterator, cast from functools import partial from typing_extensions import Literal, overload import httpx from pydantic import BaseModel from ... import _legacy_response from ..._types import NOT_GIVEN, Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given from ..._utils import is_given, maybe_transform, strip_not_given, async_maybe_transform from ..._compat import cached_property from ..._models import construct_type_unchecked from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from .input_items import ( InputItems, AsyncInputItems, InputItemsWithRawResponse, AsyncInputItemsWithRawResponse, InputItemsWithStreamingResponse, AsyncInputItemsWithStreamingResponse, ) from ..._streaming import Stream, AsyncStream from ...lib._tools import PydanticFunctionTool, ResponsesPydanticFunctionTool from .input_tokens import ( InputTokens, AsyncInputTokens, InputTokensWithRawResponse, AsyncInputTokensWithRawResponse, InputTokensWithStreamingResponse, AsyncInputTokensWithStreamingResponse, ) from ..._exceptions import OpenAIError from ..._base_client import _merge_mappings, make_request_options from ...types.responses import ( response_create_params, response_compact_params, response_retrieve_params, responses_client_event_param, ) from ...lib._parsing._responses import ( TextFormatT, parse_response, type_to_text_format_param as _type_to_text_format_param, ) from ...types.responses.response import Response from ...types.responses.tool_param import ToolParam, ParseableToolParam from ...types.shared_params.metadata import Metadata from ...types.shared_params.reasoning import Reasoning from ...types.responses.parsed_response import ParsedResponse from ...lib.streaming.responses._responses import ResponseStreamManager, AsyncResponseStreamManager from ...types.responses.compacted_response import CompactedResponse from ...types.websocket_connection_options import WebSocketConnectionOptions from ...types.responses.response_includable import ResponseIncludable from ...types.shared_params.responses_model import ResponsesModel from ...types.responses.response_input_param import ResponseInputParam from ...types.responses.response_prompt_param import ResponsePromptParam from ...types.responses.response_stream_event import ResponseStreamEvent from ...types.responses.responses_client_event import ResponsesClientEvent from ...types.responses.responses_server_event import ResponsesServerEvent from ...types.responses.response_input_item_param import ResponseInputItemParam from ...types.responses.response_text_config_param import ResponseTextConfigParam from ...types.responses.responses_client_event_param import ResponsesClientEventParam if TYPE_CHECKING: from websockets.sync.client import ClientConnection as WebSocketConnection from websockets.asyncio.client import ClientConnection as AsyncWebSocketConnection from ..._client import OpenAI, AsyncOpenAI __all__ = ["Responses", "AsyncResponses"] log: logging.Logger = logging.getLogger(__name__) class Responses(SyncAPIResource): @cached_property def input_items(self) -> InputItems: return InputItems(self._client) @cached_property def input_tokens(self) -> InputTokens: return InputTokens(self._client) @cached_property def with_raw_response(self) -> ResponsesWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return ResponsesWithRawResponse(self) @cached_property def with_streaming_response(self) -> ResponsesWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return ResponsesWithStreamingResponse(self) @overload def create( self, *, background: Optional[bool] | Omit = omit, context_management: Optional[Iterable[response_create_params.ContextManagement]] | Omit = omit, conversation: Optional[response_create_params.Conversation] | Omit = omit, include: Optional[List[ResponseIncludable]] | Omit = omit, input: Union[str, ResponseInputParam] | Omit = omit, instructions: Optional[str] | Omit = omit, max_output_tokens: Optional[int] | Omit = omit, max_tool_calls: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: ResponsesModel | Omit = omit, parallel_tool_calls: Optional[bool] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, prompt: Optional[ResponsePromptParam] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning: Optional[Reasoning] | Omit = omit, safety_identifier: str | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, store: Optional[bool] | Omit = omit, stream: Optional[Literal[False]] | Omit = omit, stream_options: Optional[response_create_params.StreamOptions] | Omit = omit, temperature: Optional[float] | Omit = omit, text: ResponseTextConfigParam | Omit = omit, tool_choice: response_create_params.ToolChoice | Omit = omit, tools: Iterable[ToolParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation: Optional[Literal["auto", "disabled"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Response: """Creates a model response. Provide [text](https://platform.openai.com/docs/guides/text) or [image](https://platform.openai.com/docs/guides/images) inputs to generate [text](https://platform.openai.com/docs/guides/text) or [JSON](https://platform.openai.com/docs/guides/structured-outputs) outputs. Have the model call your own [custom code](https://platform.openai.com/docs/guides/function-calling) or use built-in [tools](https://platform.openai.com/docs/guides/tools) like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search) to use your own data as input for the model's response. Args: background: Whether to run the model response in the background. [Learn more](https://platform.openai.com/docs/guides/background). context_management: Context management configuration for this request. conversation: The conversation that this response belongs to. Items from this conversation are prepended to `input_items` for this response request. Input items and output items from this response are automatically added to this conversation after this response completes. include: Specify additional output data to include in the model response. Currently supported values are: - `web_search_call.action.sources`: Include the sources of the web search tool call. - `code_interpreter_call.outputs`: Includes the outputs of python code execution in code interpreter tool call items. - `computer_call_output.output.image_url`: Include image urls from the computer call output. - `file_search_call.results`: Include the search results of the file search tool call. - `message.input_image.image_url`: Include image urls from the input message. - `message.output_text.logprobs`: Include logprobs with assistant messages. - `reasoning.encrypted_content`: Includes an encrypted version of reasoning tokens in reasoning item outputs. This enables reasoning items to be used in multi-turn conversations when using the Responses API statelessly (like when the `store` parameter is set to `false`, or when an organization is enrolled in the zero data retention program). input: Text, image, or file inputs to the model, used to generate a response. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Image inputs](https://platform.openai.com/docs/guides/images) - [File inputs](https://platform.openai.com/docs/guides/pdf-files) - [Conversation state](https://platform.openai.com/docs/guides/conversation-state) - [Function calling](https://platform.openai.com/docs/guides/function-calling) instructions: A system (or developer) message inserted into the model's context. When using along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses. max_output_tokens: An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). max_tool_calls: The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. parallel_tool_calls: Whether to allow the model to run tool calls in parallel. previous_response_id: The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://platform.openai.com/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`. prompt: Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). prompt_cache_key: Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://platform.openai.com/docs/guides/prompt-caching). prompt_cache_retention: The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). reasoning: **gpt-5 and o-series models only** Configuration options for [reasoning models](https://platform.openai.com/docs/guides/reasoning). safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). service_tier: Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier. - When not set, the default behavior is 'auto'. When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. store: Whether to store the generated model response for later retrieval via API. stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) for more information. stream_options: Options for streaming responses. Only set this when you set `stream: true`. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. text: Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) tool_choice: How the model should select which tool (or tools) to use when generating a response. See the `tools` parameter to see how to specify which tools the model can call. tools: An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. We support the following categories of tools: - **Built-in tools**: Tools that are provided by OpenAI that extend the model's capabilities, like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). - **MCP Tools**: Integrations with third-party systems via custom MCP servers or predefined connectors such as Google Drive and SharePoint. Learn more about [MCP Tools](https://platform.openai.com/docs/guides/tools-connectors-mcp). - **Function calls (custom tools)**: Functions that are defined by you, enabling the model to call your own code with strongly typed arguments and outputs. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). You can also use custom tools to call your own code. top_logprobs: An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. truncation: The truncation strategy to use for the model response. - `auto`: If the input to this Response exceeds the model's context window size, the model will truncate the response to fit the context window by dropping items from the beginning of the conversation. - `disabled` (default): If the input size will exceed the context window size for a model, the request will fail with a 400 error. user: This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations. A stable identifier for your end-users. Used to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload def create( self, *, stream: Literal[True], background: Optional[bool] | Omit = omit, context_management: Optional[Iterable[response_create_params.ContextManagement]] | Omit = omit, conversation: Optional[response_create_params.Conversation] | Omit = omit, include: Optional[List[ResponseIncludable]] | Omit = omit, input: Union[str, ResponseInputParam] | Omit = omit, instructions: Optional[str] | Omit = omit, max_output_tokens: Optional[int] | Omit = omit, max_tool_calls: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: ResponsesModel | Omit = omit, parallel_tool_calls: Optional[bool] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, prompt: Optional[ResponsePromptParam] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning: Optional[Reasoning] | Omit = omit, safety_identifier: str | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, store: Optional[bool] | Omit = omit, stream_options: Optional[response_create_params.StreamOptions] | Omit = omit, temperature: Optional[float] | Omit = omit, text: ResponseTextConfigParam | Omit = omit, tool_choice: response_create_params.ToolChoice | Omit = omit, tools: Iterable[ToolParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation: Optional[Literal["auto", "disabled"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Stream[ResponseStreamEvent]: """Creates a model response. Provide [text](https://platform.openai.com/docs/guides/text) or [image](https://platform.openai.com/docs/guides/images) inputs to generate [text](https://platform.openai.com/docs/guides/text) or [JSON](https://platform.openai.com/docs/guides/structured-outputs) outputs. Have the model call your own [custom code](https://platform.openai.com/docs/guides/function-calling) or use built-in [tools](https://platform.openai.com/docs/guides/tools) like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search) to use your own data as input for the model's response. Args: stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) for more information. background: Whether to run the model response in the background. [Learn more](https://platform.openai.com/docs/guides/background). context_management: Context management configuration for this request. conversation: The conversation that this response belongs to. Items from this conversation are prepended to `input_items` for this response request. Input items and output items from this response are automatically added to this conversation after this response completes. include: Specify additional output data to include in the model response. Currently supported values are: - `web_search_call.action.sources`: Include the sources of the web search tool call. - `code_interpreter_call.outputs`: Includes the outputs of python code execution in code interpreter tool call items. - `computer_call_output.output.image_url`: Include image urls from the computer call output. - `file_search_call.results`: Include the search results of the file search tool call. - `message.input_image.image_url`: Include image urls from the input message. - `message.output_text.logprobs`: Include logprobs with assistant messages. - `reasoning.encrypted_content`: Includes an encrypted version of reasoning tokens in reasoning item outputs. This enables reasoning items to be used in multi-turn conversations when using the Responses API statelessly (like when the `store` parameter is set to `false`, or when an organization is enrolled in the zero data retention program). input: Text, image, or file inputs to the model, used to generate a response. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Image inputs](https://platform.openai.com/docs/guides/images) - [File inputs](https://platform.openai.com/docs/guides/pdf-files) - [Conversation state](https://platform.openai.com/docs/guides/conversation-state) - [Function calling](https://platform.openai.com/docs/guides/function-calling) instructions: A system (or developer) message inserted into the model's context. When using along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses. max_output_tokens: An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). max_tool_calls: The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. parallel_tool_calls: Whether to allow the model to run tool calls in parallel. previous_response_id: The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://platform.openai.com/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`. prompt: Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). prompt_cache_key: Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://platform.openai.com/docs/guides/prompt-caching). prompt_cache_retention: The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). reasoning: **gpt-5 and o-series models only** Configuration options for [reasoning models](https://platform.openai.com/docs/guides/reasoning). safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). service_tier: Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier. - When not set, the default behavior is 'auto'. When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. store: Whether to store the generated model response for later retrieval via API. stream_options: Options for streaming responses. Only set this when you set `stream: true`. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. text: Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) tool_choice: How the model should select which tool (or tools) to use when generating a response. See the `tools` parameter to see how to specify which tools the model can call. tools: An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. We support the following categories of tools: - **Built-in tools**: Tools that are provided by OpenAI that extend the model's capabilities, like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). - **MCP Tools**: Integrations with third-party systems via custom MCP servers or predefined connectors such as Google Drive and SharePoint. Learn more about [MCP Tools](https://platform.openai.com/docs/guides/tools-connectors-mcp). - **Function calls (custom tools)**: Functions that are defined by you, enabling the model to call your own code with strongly typed arguments and outputs. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). You can also use custom tools to call your own code. top_logprobs: An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. truncation: The truncation strategy to use for the model response. - `auto`: If the input to this Response exceeds the model's context window size, the model will truncate the response to fit the context window by dropping items from the beginning of the conversation. - `disabled` (default): If the input size will exceed the context window size for a model, the request will fail with a 400 error. user: This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations. A stable identifier for your end-users. Used to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload def create( self, *, stream: bool, background: Optional[bool] | Omit = omit, context_management: Optional[Iterable[response_create_params.ContextManagement]] | Omit = omit, conversation: Optional[response_create_params.Conversation] | Omit = omit, include: Optional[List[ResponseIncludable]] | Omit = omit, input: Union[str, ResponseInputParam] | Omit = omit, instructions: Optional[str] | Omit = omit, max_output_tokens: Optional[int] | Omit = omit, max_tool_calls: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: ResponsesModel | Omit = omit, parallel_tool_calls: Optional[bool] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, prompt: Optional[ResponsePromptParam] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning: Optional[Reasoning] | Omit = omit, safety_identifier: str | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, store: Optional[bool] | Omit = omit, stream_options: Optional[response_create_params.StreamOptions] | Omit = omit, temperature: Optional[float] | Omit = omit, text: ResponseTextConfigParam | Omit = omit, tool_choice: response_create_params.ToolChoice | Omit = omit, tools: Iterable[ToolParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation: Optional[Literal["auto", "disabled"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Response | Stream[ResponseStreamEvent]: """Creates a model response. Provide [text](https://platform.openai.com/docs/guides/text) or [image](https://platform.openai.com/docs/guides/images) inputs to generate [text](https://platform.openai.com/docs/guides/text) or [JSON](https://platform.openai.com/docs/guides/structured-outputs) outputs. Have the model call your own [custom code](https://platform.openai.com/docs/guides/function-calling) or use built-in [tools](https://platform.openai.com/docs/guides/tools) like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search) to use your own data as input for the model's response. Args: stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) for more information. background: Whether to run the model response in the background. [Learn more](https://platform.openai.com/docs/guides/background). context_management: Context management configuration for this request. conversation: The conversation that this response belongs to. Items from this conversation are prepended to `input_items` for this response request. Input items and output items from this response are automatically added to this conversation after this response completes. include: Specify additional output data to include in the model response. Currently supported values are: - `web_search_call.action.sources`: Include the sources of the web search tool call. - `code_interpreter_call.outputs`: Includes the outputs of python code execution in code interpreter tool call items. - `computer_call_output.output.image_url`: Include image urls from the computer call output. - `file_search_call.results`: Include the search results of the file search tool call. - `message.input_image.image_url`: Include image urls from the input message. - `message.output_text.logprobs`: Include logprobs with assistant messages. - `reasoning.encrypted_content`: Includes an encrypted version of reasoning tokens in reasoning item outputs. This enables reasoning items to be used in multi-turn conversations when using the Responses API statelessly (like when the `store` parameter is set to `false`, or when an organization is enrolled in the zero data retention program). input: Text, image, or file inputs to the model, used to generate a response. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Image inputs](https://platform.openai.com/docs/guides/images) - [File inputs](https://platform.openai.com/docs/guides/pdf-files) - [Conversation state](https://platform.openai.com/docs/guides/conversation-state) - [Function calling](https://platform.openai.com/docs/guides/function-calling) instructions: A system (or developer) message inserted into the model's context. When using along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses. max_output_tokens: An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). max_tool_calls: The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. parallel_tool_calls: Whether to allow the model to run tool calls in parallel. previous_response_id: The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://platform.openai.com/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`. prompt: Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). prompt_cache_key: Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://platform.openai.com/docs/guides/prompt-caching). prompt_cache_retention: The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). reasoning: **gpt-5 and o-series models only** Configuration options for [reasoning models](https://platform.openai.com/docs/guides/reasoning). safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). service_tier: Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier. - When not set, the default behavior is 'auto'. When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. store: Whether to store the generated model response for later retrieval via API. stream_options: Options for streaming responses. Only set this when you set `stream: true`. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. text: Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) tool_choice: How the model should select which tool (or tools) to use when generating a response. See the `tools` parameter to see how to specify which tools the model can call. tools: An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. We support the following categories of tools: - **Built-in tools**: Tools that are provided by OpenAI that extend the model's capabilities, like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). - **MCP Tools**: Integrations with third-party systems via custom MCP servers or predefined connectors such as Google Drive and SharePoint. Learn more about [MCP Tools](https://platform.openai.com/docs/guides/tools-connectors-mcp). - **Function calls (custom tools)**: Functions that are defined by you, enabling the model to call your own code with strongly typed arguments and outputs. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). You can also use custom tools to call your own code. top_logprobs: An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. truncation: The truncation strategy to use for the model response. - `auto`: If the input to this Response exceeds the model's context window size, the model will truncate the response to fit the context window by dropping items from the beginning of the conversation. - `disabled` (default): If the input size will exceed the context window size for a model, the request will fail with a 400 error. user: This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations. A stable identifier for your end-users. Used to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... def create( self, *, background: Optional[bool] | Omit = omit, context_management: Optional[Iterable[response_create_params.ContextManagement]] | Omit = omit, conversation: Optional[response_create_params.Conversation] | Omit = omit, include: Optional[List[ResponseIncludable]] | Omit = omit, input: Union[str, ResponseInputParam] | Omit = omit, instructions: Optional[str] | Omit = omit, max_output_tokens: Optional[int] | Omit = omit, max_tool_calls: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: ResponsesModel | Omit = omit, parallel_tool_calls: Optional[bool] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, prompt: Optional[ResponsePromptParam] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning: Optional[Reasoning] | Omit = omit, safety_identifier: str | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, store: Optional[bool] | Omit = omit, stream: Optional[Literal[False]] | Literal[True] | Omit = omit, stream_options: Optional[response_create_params.StreamOptions] | Omit = omit, temperature: Optional[float] | Omit = omit, text: ResponseTextConfigParam | Omit = omit, tool_choice: response_create_params.ToolChoice | Omit = omit, tools: Iterable[ToolParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation: Optional[Literal["auto", "disabled"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Response | Stream[ResponseStreamEvent]: return self._post( "/responses", body=maybe_transform( { "background": background, "context_management": context_management, "conversation": conversation, "include": include, "input": input, "instructions": instructions, "max_output_tokens": max_output_tokens, "max_tool_calls": max_tool_calls, "metadata": metadata, "model": model, "parallel_tool_calls": parallel_tool_calls, "previous_response_id": previous_response_id, "prompt": prompt, "prompt_cache_key": prompt_cache_key, "prompt_cache_retention": prompt_cache_retention, "reasoning": reasoning, "safety_identifier": safety_identifier, "service_tier": service_tier, "store": store, "stream": stream, "stream_options": stream_options, "temperature": temperature, "text": text, "tool_choice": tool_choice, "tools": tools, "top_logprobs": top_logprobs, "top_p": top_p, "truncation": truncation, "user": user, }, response_create_params.ResponseCreateParamsStreaming if stream else response_create_params.ResponseCreateParamsNonStreaming, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Response, stream=stream or False, stream_cls=Stream[ResponseStreamEvent], ) @overload def stream( self, *, response_id: str, text_format: type[TextFormatT] | Omit = omit, starting_after: int | Omit = omit, tools: Iterable[ParseableToolParam] | Omit = omit, # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> ResponseStreamManager[TextFormatT]: ... @overload def stream( self, *, input: Union[str, ResponseInputParam], model: ResponsesModel, background: Optional[bool] | Omit = omit, context_management: Optional[Iterable[response_create_params.ContextManagement]] | Omit = omit, text_format: type[TextFormatT] | Omit = omit, tools: Iterable[ParseableToolParam] | Omit = omit, conversation: Optional[response_create_params.Conversation] | Omit = omit, include: Optional[List[ResponseIncludable]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_output_tokens: Optional[int] | Omit = omit, max_tool_calls: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, parallel_tool_calls: Optional[bool] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, prompt: Optional[ResponsePromptParam] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning: Optional[Reasoning] | Omit = omit, safety_identifier: str | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, store: Optional[bool] | Omit = omit, stream_options: Optional[response_create_params.StreamOptions] | Omit = omit, temperature: Optional[float] | Omit = omit, text: ResponseTextConfigParam | Omit = omit, tool_choice: response_create_params.ToolChoice | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation: Optional[Literal["auto", "disabled"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> ResponseStreamManager[TextFormatT]: ... def stream( self, *, response_id: str | Omit = omit, input: Union[str, ResponseInputParam] | Omit = omit, model: ResponsesModel | Omit = omit, background: Optional[bool] | Omit = omit, context_management: Optional[Iterable[response_create_params.ContextManagement]] | Omit = omit, text_format: type[TextFormatT] | Omit = omit, tools: Iterable[ParseableToolParam] | Omit = omit, conversation: Optional[response_create_params.Conversation] | Omit = omit, include: Optional[List[ResponseIncludable]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_output_tokens: Optional[int] | Omit = omit, max_tool_calls: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, parallel_tool_calls: Optional[bool] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, prompt: Optional[ResponsePromptParam] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning: Optional[Reasoning] | Omit = omit, safety_identifier: str | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, store: Optional[bool] | Omit = omit, stream_options: Optional[response_create_params.StreamOptions] | Omit = omit, temperature: Optional[float] | Omit = omit, text: ResponseTextConfigParam | Omit = omit, tool_choice: response_create_params.ToolChoice | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation: Optional[Literal["auto", "disabled"]] | Omit = omit, user: str | Omit = omit, starting_after: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> ResponseStreamManager[TextFormatT]: new_response_args = { "input": input, "model": model, "context_management": context_management, "conversation": conversation, "include": include, "instructions": instructions, "max_output_tokens": max_output_tokens, "max_tool_calls": max_tool_calls, "metadata": metadata, "parallel_tool_calls": parallel_tool_calls, "previous_response_id": previous_response_id, "prompt": prompt, "prompt_cache_key": prompt_cache_key, "prompt_cache_retention": prompt_cache_retention, "reasoning": reasoning, "safety_identifier": safety_identifier, "service_tier": service_tier, "store": store, "stream_options": stream_options, "temperature": temperature, "text": text, "tool_choice": tool_choice, "top_logprobs": top_logprobs, "top_p": top_p, "truncation": truncation, "user": user, "background": background, } new_response_args_names = [k for k, v in new_response_args.items() if is_given(v)] if (is_given(response_id) or is_given(starting_after)) and len(new_response_args_names) > 0: raise ValueError( "Cannot provide both response_id/starting_after can't be provided together with " + ", ".join(new_response_args_names) ) tools = _make_tools(tools) if len(new_response_args_names) > 0: if not is_given(input): raise ValueError("input must be provided when creating a new response") if not is_given(model): raise ValueError("model must be provided when creating a new response") if is_given(text_format): if not text: text = {} if "format" in text: raise TypeError("Cannot mix and match text.format with text_format") text = copy(text) text["format"] = _type_to_text_format_param(text_format) api_request: partial[Stream[ResponseStreamEvent]] = partial( self.create, input=input, model=model, tools=tools, context_management=context_management, conversation=conversation, include=include, instructions=instructions, max_output_tokens=max_output_tokens, max_tool_calls=max_tool_calls, metadata=metadata, parallel_tool_calls=parallel_tool_calls, previous_response_id=previous_response_id, prompt=prompt, prompt_cache_key=prompt_cache_key, prompt_cache_retention=prompt_cache_retention, store=store, stream_options=stream_options, stream=True, temperature=temperature, text=text, tool_choice=tool_choice, reasoning=reasoning, safety_identifier=safety_identifier, service_tier=service_tier, top_logprobs=top_logprobs, top_p=top_p, truncation=truncation, user=user, background=background, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, ) return ResponseStreamManager(api_request, text_format=text_format, input_tools=tools, starting_after=None) else: if not is_given(response_id): raise ValueError("id must be provided when streaming an existing response") return ResponseStreamManager( lambda: self.retrieve( response_id=response_id, stream=True, include=include or [], extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, starting_after=omit, timeout=timeout, ), text_format=text_format, input_tools=tools, starting_after=starting_after if is_given(starting_after) else None, ) def parse( self, *, text_format: type[TextFormatT] | Omit = omit, background: Optional[bool] | Omit = omit, context_management: Optional[Iterable[response_create_params.ContextManagement]] | Omit = omit, conversation: Optional[response_create_params.Conversation] | Omit = omit, include: Optional[List[ResponseIncludable]] | Omit = omit, input: Union[str, ResponseInputParam] | Omit = omit, instructions: Optional[str] | Omit = omit, max_output_tokens: Optional[int] | Omit = omit, max_tool_calls: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: ResponsesModel | Omit = omit, parallel_tool_calls: Optional[bool] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, prompt: Optional[ResponsePromptParam] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning: Optional[Reasoning] | Omit = omit, safety_identifier: str | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, store: Optional[bool] | Omit = omit, stream: Optional[Literal[False]] | Literal[True] | Omit = omit, stream_options: Optional[response_create_params.StreamOptions] | Omit = omit, temperature: Optional[float] | Omit = omit, text: ResponseTextConfigParam | Omit = omit, tool_choice: response_create_params.ToolChoice | Omit = omit, tools: Iterable[ParseableToolParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation: Optional[Literal["auto", "disabled"]] | Omit = omit, user: str | Omit = omit, verbosity: Optional[Literal["low", "medium", "high"]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> ParsedResponse[TextFormatT]: if is_given(text_format): if not text: text = {} if "format" in text: raise TypeError("Cannot mix and match text.format with text_format") text = copy(text) text["format"] = _type_to_text_format_param(text_format) tools = _make_tools(tools) def parser(raw_response: Response) -> ParsedResponse[TextFormatT]: return parse_response( input_tools=tools, text_format=text_format, response=raw_response, ) return self._post( "/responses", body=maybe_transform( { "background": background, "context_management": context_management, "conversation": conversation, "include": include, "input": input, "instructions": instructions, "max_output_tokens": max_output_tokens, "max_tool_calls": max_tool_calls, "metadata": metadata, "model": model, "parallel_tool_calls": parallel_tool_calls, "previous_response_id": previous_response_id, "prompt": prompt, "prompt_cache_key": prompt_cache_key, "prompt_cache_retention": prompt_cache_retention, "reasoning": reasoning, "safety_identifier": safety_identifier, "service_tier": service_tier, "store": store, "stream": stream, "stream_options": stream_options, "temperature": temperature, "text": text, "tool_choice": tool_choice, "tools": tools, "top_logprobs": top_logprobs, "top_p": top_p, "truncation": truncation, "user": user, "verbosity": verbosity, }, response_create_params.ResponseCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, post_parser=parser, ), # we turn the `Response` instance into a `ParsedResponse` # in the `parser` function above cast_to=cast(Type[ParsedResponse[TextFormatT]], Response), ) @overload def retrieve( self, response_id: str, *, include: List[ResponseIncludable] | Omit = omit, include_obfuscation: bool | Omit = omit, starting_after: int | Omit = omit, stream: Literal[False] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Response: ... @overload def retrieve( self, response_id: str, *, stream: Literal[True], include: List[ResponseIncludable] | Omit = omit, starting_after: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Stream[ResponseStreamEvent]: ... @overload def retrieve( self, response_id: str, *, stream: bool, include: List[ResponseIncludable] | Omit = omit, starting_after: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Response | Stream[ResponseStreamEvent]: ... @overload def retrieve( self, response_id: str, *, stream: bool = False, include: List[ResponseIncludable] | Omit = omit, starting_after: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Response | Stream[ResponseStreamEvent]: """ Retrieves a model response with the given ID. Args: include: Additional fields to include in the response. See the `include` parameter for Response creation above for more information. include_obfuscation: When true, stream obfuscation will be enabled. Stream obfuscation adds random characters to an `obfuscation` field on streaming delta events to normalize payload sizes as a mitigation to certain side-channel attacks. These obfuscation fields are included by default, but add a small amount of overhead to the data stream. You can set `include_obfuscation` to false to optimize for bandwidth if you trust the network links between your application and the OpenAI API. starting_after: The sequence number of the event after which to start streaming. stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) for more information. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload def retrieve( self, response_id: str, *, stream: Literal[True], include: List[ResponseIncludable] | Omit = omit, include_obfuscation: bool | Omit = omit, starting_after: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Stream[ResponseStreamEvent]: """ Retrieves a model response with the given ID. Args: stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) for more information. include: Additional fields to include in the response. See the `include` parameter for Response creation above for more information. include_obfuscation: When true, stream obfuscation will be enabled. Stream obfuscation adds random characters to an `obfuscation` field on streaming delta events to normalize payload sizes as a mitigation to certain side-channel attacks. These obfuscation fields are included by default, but add a small amount of overhead to the data stream. You can set `include_obfuscation` to false to optimize for bandwidth if you trust the network links between your application and the OpenAI API. starting_after: The sequence number of the event after which to start streaming. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload def retrieve( self, response_id: str, *, stream: bool, include: List[ResponseIncludable] | Omit = omit, include_obfuscation: bool | Omit = omit, starting_after: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Response | Stream[ResponseStreamEvent]: """ Retrieves a model response with the given ID. Args: stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) for more information. include: Additional fields to include in the response. See the `include` parameter for Response creation above for more information. include_obfuscation: When true, stream obfuscation will be enabled. Stream obfuscation adds random characters to an `obfuscation` field on streaming delta events to normalize payload sizes as a mitigation to certain side-channel attacks. These obfuscation fields are included by default, but add a small amount of overhead to the data stream. You can set `include_obfuscation` to false to optimize for bandwidth if you trust the network links between your application and the OpenAI API. starting_after: The sequence number of the event after which to start streaming. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... def retrieve( self, response_id: str, *, include: List[ResponseIncludable] | Omit = omit, include_obfuscation: bool | Omit = omit, starting_after: int | Omit = omit, stream: Literal[False] | Literal[True] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Response | Stream[ResponseStreamEvent]: if not response_id: raise ValueError(f"Expected a non-empty value for `response_id` but received {response_id!r}") return self._get( f"/responses/{response_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "include": include, "include_obfuscation": include_obfuscation, "starting_after": starting_after, "stream": stream, }, response_retrieve_params.ResponseRetrieveParams, ), ), cast_to=Response, stream=stream or False, stream_cls=Stream[ResponseStreamEvent], ) def delete( self, response_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Deletes a model response with the given ID. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not response_id: raise ValueError(f"Expected a non-empty value for `response_id` but received {response_id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._delete( f"/responses/{response_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=NoneType, ) def cancel( self, response_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Response: """Cancels a model response with the given ID. Only responses created with the `background` parameter set to `true` can be cancelled. [Learn more](https://platform.openai.com/docs/guides/background). Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not response_id: raise ValueError(f"Expected a non-empty value for `response_id` but received {response_id!r}") return self._post( f"/responses/{response_id}/cancel", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Response, ) def compact( self, *, model: Union[ Literal[ "gpt-5.4", "gpt-5.4-mini", "gpt-5.4-nano", "gpt-5.4-mini-2026-03-17", "gpt-5.4-nano-2026-03-17", "gpt-5.3-chat-latest", "gpt-5.2", "gpt-5.2-2025-12-11", "gpt-5.2-chat-latest", "gpt-5.2-pro", "gpt-5.2-pro-2025-12-11", "gpt-5.1", "gpt-5.1-2025-11-13", "gpt-5.1-codex", "gpt-5.1-mini", "gpt-5.1-chat-latest", "gpt-5", "gpt-5-mini", "gpt-5-nano", "gpt-5-2025-08-07", "gpt-5-mini-2025-08-07", "gpt-5-nano-2025-08-07", "gpt-5-chat-latest", "gpt-4.1", "gpt-4.1-mini", "gpt-4.1-nano", "gpt-4.1-2025-04-14", "gpt-4.1-mini-2025-04-14", "gpt-4.1-nano-2025-04-14", "o4-mini", "o4-mini-2025-04-16", "o3", "o3-2025-04-16", "o3-mini", "o3-mini-2025-01-31", "o1", "o1-2024-12-17", "o1-preview", "o1-preview-2024-09-12", "o1-mini", "o1-mini-2024-09-12", "gpt-4o", "gpt-4o-2024-11-20", "gpt-4o-2024-08-06", "gpt-4o-2024-05-13", "gpt-4o-audio-preview", "gpt-4o-audio-preview-2024-10-01", "gpt-4o-audio-preview-2024-12-17", "gpt-4o-audio-preview-2025-06-03", "gpt-4o-mini-audio-preview", "gpt-4o-mini-audio-preview-2024-12-17", "gpt-4o-search-preview", "gpt-4o-mini-search-preview", "gpt-4o-search-preview-2025-03-11", "gpt-4o-mini-search-preview-2025-03-11", "chatgpt-4o-latest", "codex-mini-latest", "gpt-4o-mini", "gpt-4o-mini-2024-07-18", "gpt-4-turbo", "gpt-4-turbo-2024-04-09", "gpt-4-0125-preview", "gpt-4-turbo-preview", "gpt-4-1106-preview", "gpt-4-vision-preview", "gpt-4", "gpt-4-0314", "gpt-4-0613", "gpt-4-32k", "gpt-4-32k-0314", "gpt-4-32k-0613", "gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-3.5-turbo-0301", "gpt-3.5-turbo-0613", "gpt-3.5-turbo-1106", "gpt-3.5-turbo-0125", "gpt-3.5-turbo-16k-0613", "o1-pro", "o1-pro-2025-03-19", "o3-pro", "o3-pro-2025-06-10", "o3-deep-research", "o3-deep-research-2025-06-26", "o4-mini-deep-research", "o4-mini-deep-research-2025-06-26", "computer-use-preview", "computer-use-preview-2025-03-11", "gpt-5-codex", "gpt-5-pro", "gpt-5-pro-2025-10-06", "gpt-5.1-codex-max", ], str, None, ], input: Union[str, Iterable[ResponseInputItemParam], None] | Omit = omit, instructions: Optional[str] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, prompt_cache_key: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CompactedResponse: """Compact a conversation. Returns a compacted response object. Learn when and how to compact long-running conversations in the [conversation state guide](https://platform.openai.com/docs/guides/conversation-state#managing-the-context-window). For ZDR-compatible compaction details, see [Compaction (advanced)](https://platform.openai.com/docs/guides/conversation-state#compaction-advanced). Args: model: Model ID used to generate the response, like `gpt-5` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. input: Text, image, or file inputs to the model, used to generate a response instructions: A system (or developer) message inserted into the model's context. When used along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses. previous_response_id: The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://platform.openai.com/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`. prompt_cache_key: A key to use when reading from or writing to the prompt cache. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._post( "/responses/compact", body=maybe_transform( { "model": model, "input": input, "instructions": instructions, "previous_response_id": previous_response_id, "prompt_cache_key": prompt_cache_key, }, response_compact_params.ResponseCompactParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=CompactedResponse, ) def connect( self, extra_query: Query = {}, extra_headers: Headers = {}, websocket_connection_options: WebSocketConnectionOptions = {}, ) -> ResponsesConnectionManager: """Connect to a persistent Responses API WebSocket. Send `response.create` events and receive response stream events over the socket. """ return ResponsesConnectionManager( client=self._client, extra_query=extra_query, extra_headers=extra_headers, websocket_connection_options=websocket_connection_options, ) class AsyncResponses(AsyncAPIResource): @cached_property def input_items(self) -> AsyncInputItems: return AsyncInputItems(self._client) @cached_property def input_tokens(self) -> AsyncInputTokens: return AsyncInputTokens(self._client) @cached_property def with_raw_response(self) -> AsyncResponsesWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncResponsesWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncResponsesWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncResponsesWithStreamingResponse(self) @overload async def create( self, *, background: Optional[bool] | Omit = omit, context_management: Optional[Iterable[response_create_params.ContextManagement]] | Omit = omit, conversation: Optional[response_create_params.Conversation] | Omit = omit, include: Optional[List[ResponseIncludable]] | Omit = omit, input: Union[str, ResponseInputParam] | Omit = omit, instructions: Optional[str] | Omit = omit, max_output_tokens: Optional[int] | Omit = omit, max_tool_calls: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: ResponsesModel | Omit = omit, parallel_tool_calls: Optional[bool] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, prompt: Optional[ResponsePromptParam] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning: Optional[Reasoning] | Omit = omit, safety_identifier: str | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, store: Optional[bool] | Omit = omit, stream: Optional[Literal[False]] | Omit = omit, stream_options: Optional[response_create_params.StreamOptions] | Omit = omit, temperature: Optional[float] | Omit = omit, text: ResponseTextConfigParam | Omit = omit, tool_choice: response_create_params.ToolChoice | Omit = omit, tools: Iterable[ToolParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation: Optional[Literal["auto", "disabled"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Response: """Creates a model response. Provide [text](https://platform.openai.com/docs/guides/text) or [image](https://platform.openai.com/docs/guides/images) inputs to generate [text](https://platform.openai.com/docs/guides/text) or [JSON](https://platform.openai.com/docs/guides/structured-outputs) outputs. Have the model call your own [custom code](https://platform.openai.com/docs/guides/function-calling) or use built-in [tools](https://platform.openai.com/docs/guides/tools) like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search) to use your own data as input for the model's response. Args: background: Whether to run the model response in the background. [Learn more](https://platform.openai.com/docs/guides/background). context_management: Context management configuration for this request. conversation: The conversation that this response belongs to. Items from this conversation are prepended to `input_items` for this response request. Input items and output items from this response are automatically added to this conversation after this response completes. include: Specify additional output data to include in the model response. Currently supported values are: - `web_search_call.action.sources`: Include the sources of the web search tool call. - `code_interpreter_call.outputs`: Includes the outputs of python code execution in code interpreter tool call items. - `computer_call_output.output.image_url`: Include image urls from the computer call output. - `file_search_call.results`: Include the search results of the file search tool call. - `message.input_image.image_url`: Include image urls from the input message. - `message.output_text.logprobs`: Include logprobs with assistant messages. - `reasoning.encrypted_content`: Includes an encrypted version of reasoning tokens in reasoning item outputs. This enables reasoning items to be used in multi-turn conversations when using the Responses API statelessly (like when the `store` parameter is set to `false`, or when an organization is enrolled in the zero data retention program). input: Text, image, or file inputs to the model, used to generate a response. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Image inputs](https://platform.openai.com/docs/guides/images) - [File inputs](https://platform.openai.com/docs/guides/pdf-files) - [Conversation state](https://platform.openai.com/docs/guides/conversation-state) - [Function calling](https://platform.openai.com/docs/guides/function-calling) instructions: A system (or developer) message inserted into the model's context. When using along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses. max_output_tokens: An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). max_tool_calls: The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. parallel_tool_calls: Whether to allow the model to run tool calls in parallel. previous_response_id: The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://platform.openai.com/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`. prompt: Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). prompt_cache_key: Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://platform.openai.com/docs/guides/prompt-caching). prompt_cache_retention: The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). reasoning: **gpt-5 and o-series models only** Configuration options for [reasoning models](https://platform.openai.com/docs/guides/reasoning). safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). service_tier: Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier. - When not set, the default behavior is 'auto'. When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. store: Whether to store the generated model response for later retrieval via API. stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) for more information. stream_options: Options for streaming responses. Only set this when you set `stream: true`. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. text: Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) tool_choice: How the model should select which tool (or tools) to use when generating a response. See the `tools` parameter to see how to specify which tools the model can call. tools: An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. We support the following categories of tools: - **Built-in tools**: Tools that are provided by OpenAI that extend the model's capabilities, like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). - **MCP Tools**: Integrations with third-party systems via custom MCP servers or predefined connectors such as Google Drive and SharePoint. Learn more about [MCP Tools](https://platform.openai.com/docs/guides/tools-connectors-mcp). - **Function calls (custom tools)**: Functions that are defined by you, enabling the model to call your own code with strongly typed arguments and outputs. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). You can also use custom tools to call your own code. top_logprobs: An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. truncation: The truncation strategy to use for the model response. - `auto`: If the input to this Response exceeds the model's context window size, the model will truncate the response to fit the context window by dropping items from the beginning of the conversation. - `disabled` (default): If the input size will exceed the context window size for a model, the request will fail with a 400 error. user: This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations. A stable identifier for your end-users. Used to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload async def create( self, *, stream: Literal[True], background: Optional[bool] | Omit = omit, context_management: Optional[Iterable[response_create_params.ContextManagement]] | Omit = omit, conversation: Optional[response_create_params.Conversation] | Omit = omit, include: Optional[List[ResponseIncludable]] | Omit = omit, input: Union[str, ResponseInputParam] | Omit = omit, instructions: Optional[str] | Omit = omit, max_output_tokens: Optional[int] | Omit = omit, max_tool_calls: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: ResponsesModel | Omit = omit, parallel_tool_calls: Optional[bool] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, prompt: Optional[ResponsePromptParam] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning: Optional[Reasoning] | Omit = omit, safety_identifier: str | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, store: Optional[bool] | Omit = omit, stream_options: Optional[response_create_params.StreamOptions] | Omit = omit, temperature: Optional[float] | Omit = omit, text: ResponseTextConfigParam | Omit = omit, tool_choice: response_create_params.ToolChoice | Omit = omit, tools: Iterable[ToolParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation: Optional[Literal["auto", "disabled"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncStream[ResponseStreamEvent]: """Creates a model response. Provide [text](https://platform.openai.com/docs/guides/text) or [image](https://platform.openai.com/docs/guides/images) inputs to generate [text](https://platform.openai.com/docs/guides/text) or [JSON](https://platform.openai.com/docs/guides/structured-outputs) outputs. Have the model call your own [custom code](https://platform.openai.com/docs/guides/function-calling) or use built-in [tools](https://platform.openai.com/docs/guides/tools) like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search) to use your own data as input for the model's response. Args: stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) for more information. background: Whether to run the model response in the background. [Learn more](https://platform.openai.com/docs/guides/background). context_management: Context management configuration for this request. conversation: The conversation that this response belongs to. Items from this conversation are prepended to `input_items` for this response request. Input items and output items from this response are automatically added to this conversation after this response completes. include: Specify additional output data to include in the model response. Currently supported values are: - `web_search_call.action.sources`: Include the sources of the web search tool call. - `code_interpreter_call.outputs`: Includes the outputs of python code execution in code interpreter tool call items. - `computer_call_output.output.image_url`: Include image urls from the computer call output. - `file_search_call.results`: Include the search results of the file search tool call. - `message.input_image.image_url`: Include image urls from the input message. - `message.output_text.logprobs`: Include logprobs with assistant messages. - `reasoning.encrypted_content`: Includes an encrypted version of reasoning tokens in reasoning item outputs. This enables reasoning items to be used in multi-turn conversations when using the Responses API statelessly (like when the `store` parameter is set to `false`, or when an organization is enrolled in the zero data retention program). input: Text, image, or file inputs to the model, used to generate a response. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Image inputs](https://platform.openai.com/docs/guides/images) - [File inputs](https://platform.openai.com/docs/guides/pdf-files) - [Conversation state](https://platform.openai.com/docs/guides/conversation-state) - [Function calling](https://platform.openai.com/docs/guides/function-calling) instructions: A system (or developer) message inserted into the model's context. When using along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses. max_output_tokens: An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). max_tool_calls: The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. parallel_tool_calls: Whether to allow the model to run tool calls in parallel. previous_response_id: The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://platform.openai.com/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`. prompt: Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). prompt_cache_key: Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://platform.openai.com/docs/guides/prompt-caching). prompt_cache_retention: The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). reasoning: **gpt-5 and o-series models only** Configuration options for [reasoning models](https://platform.openai.com/docs/guides/reasoning). safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). service_tier: Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier. - When not set, the default behavior is 'auto'. When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. store: Whether to store the generated model response for later retrieval via API. stream_options: Options for streaming responses. Only set this when you set `stream: true`. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. text: Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) tool_choice: How the model should select which tool (or tools) to use when generating a response. See the `tools` parameter to see how to specify which tools the model can call. tools: An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. We support the following categories of tools: - **Built-in tools**: Tools that are provided by OpenAI that extend the model's capabilities, like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). - **MCP Tools**: Integrations with third-party systems via custom MCP servers or predefined connectors such as Google Drive and SharePoint. Learn more about [MCP Tools](https://platform.openai.com/docs/guides/tools-connectors-mcp). - **Function calls (custom tools)**: Functions that are defined by you, enabling the model to call your own code with strongly typed arguments and outputs. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). You can also use custom tools to call your own code. top_logprobs: An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. truncation: The truncation strategy to use for the model response. - `auto`: If the input to this Response exceeds the model's context window size, the model will truncate the response to fit the context window by dropping items from the beginning of the conversation. - `disabled` (default): If the input size will exceed the context window size for a model, the request will fail with a 400 error. user: This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations. A stable identifier for your end-users. Used to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload async def create( self, *, stream: bool, background: Optional[bool] | Omit = omit, context_management: Optional[Iterable[response_create_params.ContextManagement]] | Omit = omit, conversation: Optional[response_create_params.Conversation] | Omit = omit, include: Optional[List[ResponseIncludable]] | Omit = omit, input: Union[str, ResponseInputParam] | Omit = omit, instructions: Optional[str] | Omit = omit, max_output_tokens: Optional[int] | Omit = omit, max_tool_calls: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: ResponsesModel | Omit = omit, parallel_tool_calls: Optional[bool] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, prompt: Optional[ResponsePromptParam] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning: Optional[Reasoning] | Omit = omit, safety_identifier: str | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, store: Optional[bool] | Omit = omit, stream_options: Optional[response_create_params.StreamOptions] | Omit = omit, temperature: Optional[float] | Omit = omit, text: ResponseTextConfigParam | Omit = omit, tool_choice: response_create_params.ToolChoice | Omit = omit, tools: Iterable[ToolParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation: Optional[Literal["auto", "disabled"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Response | AsyncStream[ResponseStreamEvent]: """Creates a model response. Provide [text](https://platform.openai.com/docs/guides/text) or [image](https://platform.openai.com/docs/guides/images) inputs to generate [text](https://platform.openai.com/docs/guides/text) or [JSON](https://platform.openai.com/docs/guides/structured-outputs) outputs. Have the model call your own [custom code](https://platform.openai.com/docs/guides/function-calling) or use built-in [tools](https://platform.openai.com/docs/guides/tools) like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search) to use your own data as input for the model's response. Args: stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) for more information. background: Whether to run the model response in the background. [Learn more](https://platform.openai.com/docs/guides/background). context_management: Context management configuration for this request. conversation: The conversation that this response belongs to. Items from this conversation are prepended to `input_items` for this response request. Input items and output items from this response are automatically added to this conversation after this response completes. include: Specify additional output data to include in the model response. Currently supported values are: - `web_search_call.action.sources`: Include the sources of the web search tool call. - `code_interpreter_call.outputs`: Includes the outputs of python code execution in code interpreter tool call items. - `computer_call_output.output.image_url`: Include image urls from the computer call output. - `file_search_call.results`: Include the search results of the file search tool call. - `message.input_image.image_url`: Include image urls from the input message. - `message.output_text.logprobs`: Include logprobs with assistant messages. - `reasoning.encrypted_content`: Includes an encrypted version of reasoning tokens in reasoning item outputs. This enables reasoning items to be used in multi-turn conversations when using the Responses API statelessly (like when the `store` parameter is set to `false`, or when an organization is enrolled in the zero data retention program). input: Text, image, or file inputs to the model, used to generate a response. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Image inputs](https://platform.openai.com/docs/guides/images) - [File inputs](https://platform.openai.com/docs/guides/pdf-files) - [Conversation state](https://platform.openai.com/docs/guides/conversation-state) - [Function calling](https://platform.openai.com/docs/guides/function-calling) instructions: A system (or developer) message inserted into the model's context. When using along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses. max_output_tokens: An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). max_tool_calls: The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. model: Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. parallel_tool_calls: Whether to allow the model to run tool calls in parallel. previous_response_id: The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://platform.openai.com/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`. prompt: Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). prompt_cache_key: Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://platform.openai.com/docs/guides/prompt-caching). prompt_cache_retention: The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). reasoning: **gpt-5 and o-series models only** Configuration options for [reasoning models](https://platform.openai.com/docs/guides/reasoning). safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). service_tier: Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier. - When not set, the default behavior is 'auto'. When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. store: Whether to store the generated model response for later retrieval via API. stream_options: Options for streaming responses. Only set this when you set `stream: true`. temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. text: Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) tool_choice: How the model should select which tool (or tools) to use when generating a response. See the `tools` parameter to see how to specify which tools the model can call. tools: An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. We support the following categories of tools: - **Built-in tools**: Tools that are provided by OpenAI that extend the model's capabilities, like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). - **MCP Tools**: Integrations with third-party systems via custom MCP servers or predefined connectors such as Google Drive and SharePoint. Learn more about [MCP Tools](https://platform.openai.com/docs/guides/tools-connectors-mcp). - **Function calls (custom tools)**: Functions that are defined by you, enabling the model to call your own code with strongly typed arguments and outputs. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). You can also use custom tools to call your own code. top_logprobs: An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. truncation: The truncation strategy to use for the model response. - `auto`: If the input to this Response exceeds the model's context window size, the model will truncate the response to fit the context window by dropping items from the beginning of the conversation. - `disabled` (default): If the input size will exceed the context window size for a model, the request will fail with a 400 error. user: This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations. A stable identifier for your end-users. Used to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... async def create( self, *, background: Optional[bool] | Omit = omit, context_management: Optional[Iterable[response_create_params.ContextManagement]] | Omit = omit, conversation: Optional[response_create_params.Conversation] | Omit = omit, include: Optional[List[ResponseIncludable]] | Omit = omit, input: Union[str, ResponseInputParam] | Omit = omit, instructions: Optional[str] | Omit = omit, max_output_tokens: Optional[int] | Omit = omit, max_tool_calls: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: ResponsesModel | Omit = omit, parallel_tool_calls: Optional[bool] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, prompt: Optional[ResponsePromptParam] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning: Optional[Reasoning] | Omit = omit, safety_identifier: str | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, store: Optional[bool] | Omit = omit, stream: Optional[Literal[False]] | Literal[True] | Omit = omit, stream_options: Optional[response_create_params.StreamOptions] | Omit = omit, temperature: Optional[float] | Omit = omit, text: ResponseTextConfigParam | Omit = omit, tool_choice: response_create_params.ToolChoice | Omit = omit, tools: Iterable[ToolParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation: Optional[Literal["auto", "disabled"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Response | AsyncStream[ResponseStreamEvent]: return await self._post( "/responses", body=await async_maybe_transform( { "background": background, "context_management": context_management, "conversation": conversation, "include": include, "input": input, "instructions": instructions, "max_output_tokens": max_output_tokens, "max_tool_calls": max_tool_calls, "metadata": metadata, "model": model, "parallel_tool_calls": parallel_tool_calls, "previous_response_id": previous_response_id, "prompt": prompt, "prompt_cache_key": prompt_cache_key, "prompt_cache_retention": prompt_cache_retention, "reasoning": reasoning, "safety_identifier": safety_identifier, "service_tier": service_tier, "store": store, "stream": stream, "stream_options": stream_options, "temperature": temperature, "text": text, "tool_choice": tool_choice, "tools": tools, "top_logprobs": top_logprobs, "top_p": top_p, "truncation": truncation, "user": user, }, response_create_params.ResponseCreateParamsStreaming if stream else response_create_params.ResponseCreateParamsNonStreaming, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Response, stream=stream or False, stream_cls=AsyncStream[ResponseStreamEvent], ) @overload def stream( self, *, response_id: str, text_format: type[TextFormatT] | Omit = omit, starting_after: int | Omit = omit, tools: Iterable[ParseableToolParam] | Omit = omit, # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncResponseStreamManager[TextFormatT]: ... @overload def stream( self, *, input: Union[str, ResponseInputParam], model: ResponsesModel, background: Optional[bool] | Omit = omit, context_management: Optional[Iterable[response_create_params.ContextManagement]] | Omit = omit, text_format: type[TextFormatT] | Omit = omit, tools: Iterable[ParseableToolParam] | Omit = omit, conversation: Optional[response_create_params.Conversation] | Omit = omit, include: Optional[List[ResponseIncludable]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_output_tokens: Optional[int] | Omit = omit, max_tool_calls: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, parallel_tool_calls: Optional[bool] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, prompt: Optional[ResponsePromptParam] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning: Optional[Reasoning] | Omit = omit, safety_identifier: str | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, store: Optional[bool] | Omit = omit, stream_options: Optional[response_create_params.StreamOptions] | Omit = omit, temperature: Optional[float] | Omit = omit, text: ResponseTextConfigParam | Omit = omit, tool_choice: response_create_params.ToolChoice | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation: Optional[Literal["auto", "disabled"]] | Omit = omit, user: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncResponseStreamManager[TextFormatT]: ... def stream( self, *, response_id: str | Omit = omit, input: Union[str, ResponseInputParam] | Omit = omit, model: ResponsesModel | Omit = omit, background: Optional[bool] | Omit = omit, context_management: Optional[Iterable[response_create_params.ContextManagement]] | Omit = omit, text_format: type[TextFormatT] | Omit = omit, tools: Iterable[ParseableToolParam] | Omit = omit, conversation: Optional[response_create_params.Conversation] | Omit = omit, include: Optional[List[ResponseIncludable]] | Omit = omit, instructions: Optional[str] | Omit = omit, max_output_tokens: Optional[int] | Omit = omit, max_tool_calls: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, parallel_tool_calls: Optional[bool] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, prompt: Optional[ResponsePromptParam] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning: Optional[Reasoning] | Omit = omit, safety_identifier: str | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, store: Optional[bool] | Omit = omit, stream_options: Optional[response_create_params.StreamOptions] | Omit = omit, temperature: Optional[float] | Omit = omit, text: ResponseTextConfigParam | Omit = omit, tool_choice: response_create_params.ToolChoice | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation: Optional[Literal["auto", "disabled"]] | Omit = omit, user: str | Omit = omit, starting_after: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncResponseStreamManager[TextFormatT]: new_response_args = { "input": input, "model": model, "context_management": context_management, "conversation": conversation, "include": include, "instructions": instructions, "max_output_tokens": max_output_tokens, "max_tool_calls": max_tool_calls, "metadata": metadata, "parallel_tool_calls": parallel_tool_calls, "previous_response_id": previous_response_id, "prompt": prompt, "prompt_cache_key": prompt_cache_key, "prompt_cache_retention": prompt_cache_retention, "reasoning": reasoning, "safety_identifier": safety_identifier, "service_tier": service_tier, "store": store, "stream_options": stream_options, "temperature": temperature, "text": text, "tool_choice": tool_choice, "top_logprobs": top_logprobs, "top_p": top_p, "truncation": truncation, "user": user, "background": background, } new_response_args_names = [k for k, v in new_response_args.items() if is_given(v)] if (is_given(response_id) or is_given(starting_after)) and len(new_response_args_names) > 0: raise ValueError( "Cannot provide both response_id/starting_after can't be provided together with " + ", ".join(new_response_args_names) ) tools = _make_tools(tools) if len(new_response_args_names) > 0: if isinstance(input, NotGiven): raise ValueError("input must be provided when creating a new response") if not is_given(model): raise ValueError("model must be provided when creating a new response") if is_given(text_format): if not text: text = {} if "format" in text: raise TypeError("Cannot mix and match text.format with text_format") text = copy(text) text["format"] = _type_to_text_format_param(text_format) api_request = self.create( input=input, model=model, stream=True, tools=tools, context_management=context_management, conversation=conversation, include=include, instructions=instructions, max_output_tokens=max_output_tokens, max_tool_calls=max_tool_calls, metadata=metadata, parallel_tool_calls=parallel_tool_calls, previous_response_id=previous_response_id, prompt=prompt, prompt_cache_key=prompt_cache_key, prompt_cache_retention=prompt_cache_retention, store=store, stream_options=stream_options, temperature=temperature, text=text, tool_choice=tool_choice, reasoning=reasoning, safety_identifier=safety_identifier, service_tier=service_tier, top_logprobs=top_logprobs, top_p=top_p, truncation=truncation, user=user, background=background, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, ) return AsyncResponseStreamManager( api_request, text_format=text_format, input_tools=tools, starting_after=None, ) else: if isinstance(response_id, Omit): raise ValueError("response_id must be provided when streaming an existing response") api_request = self.retrieve( response_id, stream=True, include=include or [], extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, ) return AsyncResponseStreamManager( api_request, text_format=text_format, input_tools=tools, starting_after=starting_after if is_given(starting_after) else None, ) async def parse( self, *, text_format: type[TextFormatT] | Omit = omit, background: Optional[bool] | Omit = omit, context_management: Optional[Iterable[response_create_params.ContextManagement]] | Omit = omit, conversation: Optional[response_create_params.Conversation] | Omit = omit, include: Optional[List[ResponseIncludable]] | Omit = omit, input: Union[str, ResponseInputParam] | Omit = omit, instructions: Optional[str] | Omit = omit, max_output_tokens: Optional[int] | Omit = omit, max_tool_calls: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: ResponsesModel | Omit = omit, parallel_tool_calls: Optional[bool] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, prompt: Optional[ResponsePromptParam] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning: Optional[Reasoning] | Omit = omit, safety_identifier: str | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, store: Optional[bool] | Omit = omit, stream: Optional[Literal[False]] | Literal[True] | Omit = omit, stream_options: Optional[response_create_params.StreamOptions] | Omit = omit, temperature: Optional[float] | Omit = omit, text: ResponseTextConfigParam | Omit = omit, tool_choice: response_create_params.ToolChoice | Omit = omit, tools: Iterable[ParseableToolParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation: Optional[Literal["auto", "disabled"]] | Omit = omit, user: str | Omit = omit, verbosity: Optional[Literal["low", "medium", "high"]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> ParsedResponse[TextFormatT]: if is_given(text_format): if not text: text = {} if "format" in text: raise TypeError("Cannot mix and match text.format with text_format") text = copy(text) text["format"] = _type_to_text_format_param(text_format) tools = _make_tools(tools) def parser(raw_response: Response) -> ParsedResponse[TextFormatT]: return parse_response( input_tools=tools, text_format=text_format, response=raw_response, ) return await self._post( "/responses", body=maybe_transform( { "background": background, "context_management": context_management, "conversation": conversation, "include": include, "input": input, "instructions": instructions, "max_output_tokens": max_output_tokens, "max_tool_calls": max_tool_calls, "metadata": metadata, "model": model, "parallel_tool_calls": parallel_tool_calls, "previous_response_id": previous_response_id, "prompt": prompt, "prompt_cache_key": prompt_cache_key, "prompt_cache_retention": prompt_cache_retention, "reasoning": reasoning, "safety_identifier": safety_identifier, "service_tier": service_tier, "store": store, "stream": stream, "stream_options": stream_options, "temperature": temperature, "text": text, "tool_choice": tool_choice, "tools": tools, "top_logprobs": top_logprobs, "top_p": top_p, "truncation": truncation, "user": user, "verbosity": verbosity, }, response_create_params.ResponseCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, post_parser=parser, ), # we turn the `Response` instance into a `ParsedResponse` # in the `parser` function above cast_to=cast(Type[ParsedResponse[TextFormatT]], Response), ) @overload async def retrieve( self, response_id: str, *, include: List[ResponseIncludable] | Omit = omit, include_obfuscation: bool | Omit = omit, starting_after: int | Omit = omit, stream: Literal[False] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Response: ... @overload async def retrieve( self, response_id: str, *, stream: Literal[True], include: List[ResponseIncludable] | Omit = omit, starting_after: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncStream[ResponseStreamEvent]: ... @overload async def retrieve( self, response_id: str, *, stream: bool, include: List[ResponseIncludable] | Omit = omit, starting_after: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Response | AsyncStream[ResponseStreamEvent]: ... @overload async def retrieve( self, response_id: str, *, stream: bool = False, include: List[ResponseIncludable] | Omit = omit, starting_after: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Response | AsyncStream[ResponseStreamEvent]: """ Retrieves a model response with the given ID. Args: include: Additional fields to include in the response. See the `include` parameter for Response creation above for more information. include_obfuscation: When true, stream obfuscation will be enabled. Stream obfuscation adds random characters to an `obfuscation` field on streaming delta events to normalize payload sizes as a mitigation to certain side-channel attacks. These obfuscation fields are included by default, but add a small amount of overhead to the data stream. You can set `include_obfuscation` to false to optimize for bandwidth if you trust the network links between your application and the OpenAI API. starting_after: The sequence number of the event after which to start streaming. stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) for more information. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload async def retrieve( self, response_id: str, *, stream: Literal[True], include: List[ResponseIncludable] | Omit = omit, include_obfuscation: bool | Omit = omit, starting_after: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncStream[ResponseStreamEvent]: """ Retrieves a model response with the given ID. Args: stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) for more information. include: Additional fields to include in the response. See the `include` parameter for Response creation above for more information. include_obfuscation: When true, stream obfuscation will be enabled. Stream obfuscation adds random characters to an `obfuscation` field on streaming delta events to normalize payload sizes as a mitigation to certain side-channel attacks. These obfuscation fields are included by default, but add a small amount of overhead to the data stream. You can set `include_obfuscation` to false to optimize for bandwidth if you trust the network links between your application and the OpenAI API. starting_after: The sequence number of the event after which to start streaming. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... @overload async def retrieve( self, response_id: str, *, stream: bool, include: List[ResponseIncludable] | Omit = omit, include_obfuscation: bool | Omit = omit, starting_after: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Response | AsyncStream[ResponseStreamEvent]: """ Retrieves a model response with the given ID. Args: stream: If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) for more information. include: Additional fields to include in the response. See the `include` parameter for Response creation above for more information. include_obfuscation: When true, stream obfuscation will be enabled. Stream obfuscation adds random characters to an `obfuscation` field on streaming delta events to normalize payload sizes as a mitigation to certain side-channel attacks. These obfuscation fields are included by default, but add a small amount of overhead to the data stream. You can set `include_obfuscation` to false to optimize for bandwidth if you trust the network links between your application and the OpenAI API. starting_after: The sequence number of the event after which to start streaming. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ ... async def retrieve( self, response_id: str, *, include: List[ResponseIncludable] | Omit = omit, include_obfuscation: bool | Omit = omit, starting_after: int | Omit = omit, stream: Literal[False] | Literal[True] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Response | AsyncStream[ResponseStreamEvent]: if not response_id: raise ValueError(f"Expected a non-empty value for `response_id` but received {response_id!r}") return await self._get( f"/responses/{response_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=await async_maybe_transform( { "include": include, "include_obfuscation": include_obfuscation, "starting_after": starting_after, "stream": stream, }, response_retrieve_params.ResponseRetrieveParams, ), ), cast_to=Response, stream=stream or False, stream_cls=AsyncStream[ResponseStreamEvent], ) async def delete( self, response_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Deletes a model response with the given ID. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not response_id: raise ValueError(f"Expected a non-empty value for `response_id` but received {response_id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._delete( f"/responses/{response_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=NoneType, ) async def cancel( self, response_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Response: """Cancels a model response with the given ID. Only responses created with the `background` parameter set to `true` can be cancelled. [Learn more](https://platform.openai.com/docs/guides/background). Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not response_id: raise ValueError(f"Expected a non-empty value for `response_id` but received {response_id!r}") return await self._post( f"/responses/{response_id}/cancel", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Response, ) async def compact( self, *, model: Union[ Literal[ "gpt-5.4", "gpt-5.4-mini", "gpt-5.4-nano", "gpt-5.4-mini-2026-03-17", "gpt-5.4-nano-2026-03-17", "gpt-5.3-chat-latest", "gpt-5.2", "gpt-5.2-2025-12-11", "gpt-5.2-chat-latest", "gpt-5.2-pro", "gpt-5.2-pro-2025-12-11", "gpt-5.1", "gpt-5.1-2025-11-13", "gpt-5.1-codex", "gpt-5.1-mini", "gpt-5.1-chat-latest", "gpt-5", "gpt-5-mini", "gpt-5-nano", "gpt-5-2025-08-07", "gpt-5-mini-2025-08-07", "gpt-5-nano-2025-08-07", "gpt-5-chat-latest", "gpt-4.1", "gpt-4.1-mini", "gpt-4.1-nano", "gpt-4.1-2025-04-14", "gpt-4.1-mini-2025-04-14", "gpt-4.1-nano-2025-04-14", "o4-mini", "o4-mini-2025-04-16", "o3", "o3-2025-04-16", "o3-mini", "o3-mini-2025-01-31", "o1", "o1-2024-12-17", "o1-preview", "o1-preview-2024-09-12", "o1-mini", "o1-mini-2024-09-12", "gpt-4o", "gpt-4o-2024-11-20", "gpt-4o-2024-08-06", "gpt-4o-2024-05-13", "gpt-4o-audio-preview", "gpt-4o-audio-preview-2024-10-01", "gpt-4o-audio-preview-2024-12-17", "gpt-4o-audio-preview-2025-06-03", "gpt-4o-mini-audio-preview", "gpt-4o-mini-audio-preview-2024-12-17", "gpt-4o-search-preview", "gpt-4o-mini-search-preview", "gpt-4o-search-preview-2025-03-11", "gpt-4o-mini-search-preview-2025-03-11", "chatgpt-4o-latest", "codex-mini-latest", "gpt-4o-mini", "gpt-4o-mini-2024-07-18", "gpt-4-turbo", "gpt-4-turbo-2024-04-09", "gpt-4-0125-preview", "gpt-4-turbo-preview", "gpt-4-1106-preview", "gpt-4-vision-preview", "gpt-4", "gpt-4-0314", "gpt-4-0613", "gpt-4-32k", "gpt-4-32k-0314", "gpt-4-32k-0613", "gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-3.5-turbo-0301", "gpt-3.5-turbo-0613", "gpt-3.5-turbo-1106", "gpt-3.5-turbo-0125", "gpt-3.5-turbo-16k-0613", "o1-pro", "o1-pro-2025-03-19", "o3-pro", "o3-pro-2025-06-10", "o3-deep-research", "o3-deep-research-2025-06-26", "o4-mini-deep-research", "o4-mini-deep-research-2025-06-26", "computer-use-preview", "computer-use-preview-2025-03-11", "gpt-5-codex", "gpt-5-pro", "gpt-5-pro-2025-10-06", "gpt-5.1-codex-max", ], str, None, ], input: Union[str, Iterable[ResponseInputItemParam], None] | Omit = omit, instructions: Optional[str] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, prompt_cache_key: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CompactedResponse: """Compact a conversation. Returns a compacted response object. Learn when and how to compact long-running conversations in the [conversation state guide](https://platform.openai.com/docs/guides/conversation-state#managing-the-context-window). For ZDR-compatible compaction details, see [Compaction (advanced)](https://platform.openai.com/docs/guides/conversation-state#compaction-advanced). Args: model: Model ID used to generate the response, like `gpt-5` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. input: Text, image, or file inputs to the model, used to generate a response instructions: A system (or developer) message inserted into the model's context. When used along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses. previous_response_id: The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://platform.openai.com/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`. prompt_cache_key: A key to use when reading from or writing to the prompt cache. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return await self._post( "/responses/compact", body=await async_maybe_transform( { "model": model, "input": input, "instructions": instructions, "previous_response_id": previous_response_id, "prompt_cache_key": prompt_cache_key, }, response_compact_params.ResponseCompactParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=CompactedResponse, ) def connect( self, extra_query: Query = {}, extra_headers: Headers = {}, websocket_connection_options: WebSocketConnectionOptions = {}, ) -> AsyncResponsesConnectionManager: """Connect to a persistent Responses API WebSocket. Send `response.create` events and receive response stream events over the socket. """ return AsyncResponsesConnectionManager( client=self._client, extra_query=extra_query, extra_headers=extra_headers, websocket_connection_options=websocket_connection_options, ) class ResponsesWithRawResponse: def __init__(self, responses: Responses) -> None: self._responses = responses self.create = _legacy_response.to_raw_response_wrapper( responses.create, ) self.retrieve = _legacy_response.to_raw_response_wrapper( responses.retrieve, ) self.delete = _legacy_response.to_raw_response_wrapper( responses.delete, ) self.cancel = _legacy_response.to_raw_response_wrapper( responses.cancel, ) self.compact = _legacy_response.to_raw_response_wrapper( responses.compact, ) self.parse = _legacy_response.to_raw_response_wrapper( responses.parse, ) @cached_property def input_items(self) -> InputItemsWithRawResponse: return InputItemsWithRawResponse(self._responses.input_items) @cached_property def input_tokens(self) -> InputTokensWithRawResponse: return InputTokensWithRawResponse(self._responses.input_tokens) class AsyncResponsesWithRawResponse: def __init__(self, responses: AsyncResponses) -> None: self._responses = responses self.create = _legacy_response.async_to_raw_response_wrapper( responses.create, ) self.retrieve = _legacy_response.async_to_raw_response_wrapper( responses.retrieve, ) self.delete = _legacy_response.async_to_raw_response_wrapper( responses.delete, ) self.cancel = _legacy_response.async_to_raw_response_wrapper( responses.cancel, ) self.compact = _legacy_response.async_to_raw_response_wrapper( responses.compact, ) self.parse = _legacy_response.async_to_raw_response_wrapper( responses.parse, ) @cached_property def input_items(self) -> AsyncInputItemsWithRawResponse: return AsyncInputItemsWithRawResponse(self._responses.input_items) @cached_property def input_tokens(self) -> AsyncInputTokensWithRawResponse: return AsyncInputTokensWithRawResponse(self._responses.input_tokens) class ResponsesWithStreamingResponse: def __init__(self, responses: Responses) -> None: self._responses = responses self.create = to_streamed_response_wrapper( responses.create, ) self.retrieve = to_streamed_response_wrapper( responses.retrieve, ) self.delete = to_streamed_response_wrapper( responses.delete, ) self.cancel = to_streamed_response_wrapper( responses.cancel, ) self.compact = to_streamed_response_wrapper( responses.compact, ) @cached_property def input_items(self) -> InputItemsWithStreamingResponse: return InputItemsWithStreamingResponse(self._responses.input_items) @cached_property def input_tokens(self) -> InputTokensWithStreamingResponse: return InputTokensWithStreamingResponse(self._responses.input_tokens) class AsyncResponsesWithStreamingResponse: def __init__(self, responses: AsyncResponses) -> None: self._responses = responses self.create = async_to_streamed_response_wrapper( responses.create, ) self.retrieve = async_to_streamed_response_wrapper( responses.retrieve, ) self.delete = async_to_streamed_response_wrapper( responses.delete, ) self.cancel = async_to_streamed_response_wrapper( responses.cancel, ) self.compact = async_to_streamed_response_wrapper( responses.compact, ) @cached_property def input_items(self) -> AsyncInputItemsWithStreamingResponse: return AsyncInputItemsWithStreamingResponse(self._responses.input_items) @cached_property def input_tokens(self) -> AsyncInputTokensWithStreamingResponse: return AsyncInputTokensWithStreamingResponse(self._responses.input_tokens) def _make_tools(tools: Iterable[ParseableToolParam] | Omit) -> List[ToolParam] | Omit: if not is_given(tools): return omit converted_tools: List[ToolParam] = [] for tool in tools: if tool["type"] != "function": converted_tools.append(tool) continue if "function" not in tool: # standard Responses API case converted_tools.append(tool) continue function = cast(Any, tool)["function"] # pyright: ignore[reportUnnecessaryCast] if not isinstance(function, PydanticFunctionTool): raise Exception( "Expected Chat Completions function tool shape to be created using `openai.pydantic_function_tool()`" ) assert "parameters" in function new_tool = ResponsesPydanticFunctionTool( { "type": "function", "name": function["name"], "description": function.get("description"), "parameters": function["parameters"], "strict": function.get("strict") or False, }, function.model, ) converted_tools.append(new_tool.cast()) return converted_tools class AsyncResponsesConnection: """Represents a live WebSocket connection to the Responses API""" response: AsyncResponsesResponseResource _connection: AsyncWebSocketConnection def __init__(self, connection: AsyncWebSocketConnection) -> None: self._connection = connection self.response = AsyncResponsesResponseResource(self) async def __aiter__(self) -> AsyncIterator[ResponsesServerEvent]: """ An infinite-iterator that will continue to yield events until the connection is closed. """ from websockets.exceptions import ConnectionClosedOK try: while True: yield await self.recv() except ConnectionClosedOK: return async def recv(self) -> ResponsesServerEvent: """ Receive the next message from the connection and parses it into a `ResponsesServerEvent` object. Canceling this method is safe. There's no risk of losing data. """ return self.parse_event(await self.recv_bytes()) async def recv_bytes(self) -> bytes: """Receive the next message from the connection as raw bytes. Canceling this method is safe. There's no risk of losing data. If you want to parse the message into a `ResponsesServerEvent` object like `.recv()` does, then you can call `.parse_event(data)`. """ message = await self._connection.recv(decode=False) log.debug(f"Received WebSocket message: %s", message) return message async def send(self, event: ResponsesClientEvent | ResponsesClientEventParam) -> None: data = ( event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) if isinstance(event, BaseModel) else json.dumps(await async_maybe_transform(event, ResponsesClientEventParam)) ) await self._connection.send(data) async def close(self, *, code: int = 1000, reason: str = "") -> None: await self._connection.close(code=code, reason=reason) def parse_event(self, data: str | bytes) -> ResponsesServerEvent: """ Converts a raw `str` or `bytes` message into a `ResponsesServerEvent` object. This is helpful if you're using `.recv_bytes()`. """ return cast( ResponsesServerEvent, construct_type_unchecked(value=json.loads(data), type_=cast(Any, ResponsesServerEvent)), ) class AsyncResponsesConnectionManager: """ Context manager over a `AsyncResponsesConnection` that is returned by `responses.connect()` This context manager ensures that the connection will be closed when it exits. --- Note that if your application doesn't work well with the context manager approach then you can call the `.enter()` method directly to initiate a connection. **Warning**: You must remember to close the connection with `.close()`. ```py connection = await client.responses.connect(...).enter() # ... await connection.close() ``` """ def __init__( self, *, client: AsyncOpenAI, extra_query: Query, extra_headers: Headers, websocket_connection_options: WebSocketConnectionOptions, ) -> None: self.__client = client self.__connection: AsyncResponsesConnection | None = None self.__extra_query = extra_query self.__extra_headers = extra_headers self.__websocket_connection_options = websocket_connection_options async def __aenter__(self) -> AsyncResponsesConnection: """ 👋 If your application doesn't work well with the context manager approach then you can call this method directly to initiate a connection. **Warning**: You must remember to close the connection with `.close()`. ```py connection = await client.responses.connect(...).enter() # ... await connection.close() ``` """ try: from websockets.asyncio.client import connect except ImportError as exc: raise OpenAIError("You need to install `openai[realtime]` to use this method") from exc url = self._prepare_url().copy_with( params={ **self.__client.base_url.params, **self.__extra_query, }, ) log.debug("Connecting to %s", url) if self.__websocket_connection_options: log.debug("Connection options: %s", self.__websocket_connection_options) self.__connection = AsyncResponsesConnection( await connect( str(url), user_agent_header=self.__client.user_agent, additional_headers=_merge_mappings( { **self.__client.auth_headers, }, self.__extra_headers, ), **self.__websocket_connection_options, ) ) return self.__connection enter = __aenter__ def _prepare_url(self) -> httpx.URL: if self.__client.websocket_base_url is not None: base_url = httpx.URL(self.__client.websocket_base_url) else: scheme = self.__client._base_url.scheme ws_scheme = "ws" if scheme == "http" else "wss" base_url = self.__client._base_url.copy_with(scheme=ws_scheme) merge_raw_path = base_url.raw_path.rstrip(b"/") + b"/responses" return base_url.copy_with(raw_path=merge_raw_path) async def __aexit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None ) -> None: if self.__connection is not None: await self.__connection.close() class ResponsesConnection: """Represents a live WebSocket connection to the Responses API""" response: ResponsesResponseResource _connection: WebSocketConnection def __init__(self, connection: WebSocketConnection) -> None: self._connection = connection self.response = ResponsesResponseResource(self) def __iter__(self) -> Iterator[ResponsesServerEvent]: """ An infinite-iterator that will continue to yield events until the connection is closed. """ from websockets.exceptions import ConnectionClosedOK try: while True: yield self.recv() except ConnectionClosedOK: return def recv(self) -> ResponsesServerEvent: """ Receive the next message from the connection and parses it into a `ResponsesServerEvent` object. Canceling this method is safe. There's no risk of losing data. """ return self.parse_event(self.recv_bytes()) def recv_bytes(self) -> bytes: """Receive the next message from the connection as raw bytes. Canceling this method is safe. There's no risk of losing data. If you want to parse the message into a `ResponsesServerEvent` object like `.recv()` does, then you can call `.parse_event(data)`. """ message = self._connection.recv(decode=False) log.debug(f"Received WebSocket message: %s", message) return message def send(self, event: ResponsesClientEvent | ResponsesClientEventParam) -> None: data = ( event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) if isinstance(event, BaseModel) else json.dumps(maybe_transform(event, ResponsesClientEventParam)) ) self._connection.send(data) def close(self, *, code: int = 1000, reason: str = "") -> None: self._connection.close(code=code, reason=reason) def parse_event(self, data: str | bytes) -> ResponsesServerEvent: """ Converts a raw `str` or `bytes` message into a `ResponsesServerEvent` object. This is helpful if you're using `.recv_bytes()`. """ return cast( ResponsesServerEvent, construct_type_unchecked(value=json.loads(data), type_=cast(Any, ResponsesServerEvent)), ) class ResponsesConnectionManager: """ Context manager over a `ResponsesConnection` that is returned by `responses.connect()` This context manager ensures that the connection will be closed when it exits. --- Note that if your application doesn't work well with the context manager approach then you can call the `.enter()` method directly to initiate a connection. **Warning**: You must remember to close the connection with `.close()`. ```py connection = client.responses.connect(...).enter() # ... connection.close() ``` """ def __init__( self, *, client: OpenAI, extra_query: Query, extra_headers: Headers, websocket_connection_options: WebSocketConnectionOptions, ) -> None: self.__client = client self.__connection: ResponsesConnection | None = None self.__extra_query = extra_query self.__extra_headers = extra_headers self.__websocket_connection_options = websocket_connection_options def __enter__(self) -> ResponsesConnection: """ 👋 If your application doesn't work well with the context manager approach then you can call this method directly to initiate a connection. **Warning**: You must remember to close the connection with `.close()`. ```py connection = client.responses.connect(...).enter() # ... connection.close() ``` """ try: from websockets.sync.client import connect except ImportError as exc: raise OpenAIError("You need to install `openai[realtime]` to use this method") from exc url = self._prepare_url().copy_with( params={ **self.__client.base_url.params, **self.__extra_query, }, ) log.debug("Connecting to %s", url) if self.__websocket_connection_options: log.debug("Connection options: %s", self.__websocket_connection_options) self.__connection = ResponsesConnection( connect( str(url), user_agent_header=self.__client.user_agent, additional_headers=_merge_mappings( { **self.__client.auth_headers, }, self.__extra_headers, ), **self.__websocket_connection_options, ) ) return self.__connection enter = __enter__ def _prepare_url(self) -> httpx.URL: if self.__client.websocket_base_url is not None: base_url = httpx.URL(self.__client.websocket_base_url) else: scheme = self.__client._base_url.scheme ws_scheme = "ws" if scheme == "http" else "wss" base_url = self.__client._base_url.copy_with(scheme=ws_scheme) merge_raw_path = base_url.raw_path.rstrip(b"/") + b"/responses" return base_url.copy_with(raw_path=merge_raw_path) def __exit__( self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None ) -> None: if self.__connection is not None: self.__connection.close() class BaseResponsesConnectionResource: def __init__(self, connection: ResponsesConnection) -> None: self._connection = connection class ResponsesResponseResource(BaseResponsesConnectionResource): def create( self, *, background: Optional[bool] | Omit = omit, context_management: Optional[Iterable[responses_client_event_param.ContextManagement]] | Omit = omit, conversation: Optional[responses_client_event_param.Conversation] | Omit = omit, include: Optional[List[ResponseIncludable]] | Omit = omit, input: Union[str, ResponseInputParam] | Omit = omit, instructions: Optional[str] | Omit = omit, max_output_tokens: Optional[int] | Omit = omit, max_tool_calls: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: ResponsesModel | Omit = omit, parallel_tool_calls: Optional[bool] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, prompt: Optional[ResponsePromptParam] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning: Optional[Reasoning] | Omit = omit, safety_identifier: str | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, store: Optional[bool] | Omit = omit, stream: Optional[bool] | Omit = omit, stream_options: Optional[responses_client_event_param.StreamOptions] | Omit = omit, temperature: Optional[float] | Omit = omit, text: ResponseTextConfigParam | Omit = omit, tool_choice: responses_client_event_param.ToolChoice | Omit = omit, tools: Iterable[ToolParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation: Optional[Literal["auto", "disabled"]] | Omit = omit, user: str | Omit = omit, ) -> None: self._connection.send( cast( ResponsesClientEventParam, strip_not_given( { "type": "response.create", "background": background, "context_management": context_management, "conversation": conversation, "include": include, "input": input, "instructions": instructions, "max_output_tokens": max_output_tokens, "max_tool_calls": max_tool_calls, "metadata": metadata, "model": model, "parallel_tool_calls": parallel_tool_calls, "previous_response_id": previous_response_id, "prompt": prompt, "prompt_cache_key": prompt_cache_key, "prompt_cache_retention": prompt_cache_retention, "reasoning": reasoning, "safety_identifier": safety_identifier, "service_tier": service_tier, "store": store, "stream": stream, "stream_options": stream_options, "temperature": temperature, "text": text, "tool_choice": tool_choice, "tools": tools, "top_logprobs": top_logprobs, "top_p": top_p, "truncation": truncation, "user": user, } ), ) ) class BaseAsyncResponsesConnectionResource: def __init__(self, connection: AsyncResponsesConnection) -> None: self._connection = connection class AsyncResponsesResponseResource(BaseAsyncResponsesConnectionResource): async def create( self, *, background: Optional[bool] | Omit = omit, context_management: Optional[Iterable[responses_client_event_param.ContextManagement]] | Omit = omit, conversation: Optional[responses_client_event_param.Conversation] | Omit = omit, include: Optional[List[ResponseIncludable]] | Omit = omit, input: Union[str, ResponseInputParam] | Omit = omit, instructions: Optional[str] | Omit = omit, max_output_tokens: Optional[int] | Omit = omit, max_tool_calls: Optional[int] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, model: ResponsesModel | Omit = omit, parallel_tool_calls: Optional[bool] | Omit = omit, previous_response_id: Optional[str] | Omit = omit, prompt: Optional[ResponsePromptParam] | Omit = omit, prompt_cache_key: str | Omit = omit, prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, reasoning: Optional[Reasoning] | Omit = omit, safety_identifier: str | Omit = omit, service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, store: Optional[bool] | Omit = omit, stream: Optional[bool] | Omit = omit, stream_options: Optional[responses_client_event_param.StreamOptions] | Omit = omit, temperature: Optional[float] | Omit = omit, text: ResponseTextConfigParam | Omit = omit, tool_choice: responses_client_event_param.ToolChoice | Omit = omit, tools: Iterable[ToolParam] | Omit = omit, top_logprobs: Optional[int] | Omit = omit, top_p: Optional[float] | Omit = omit, truncation: Optional[Literal["auto", "disabled"]] | Omit = omit, user: str | Omit = omit, ) -> None: await self._connection.send( cast( ResponsesClientEventParam, strip_not_given( { "type": "response.create", "background": background, "context_management": context_management, "conversation": conversation, "include": include, "input": input, "instructions": instructions, "max_output_tokens": max_output_tokens, "max_tool_calls": max_tool_calls, "metadata": metadata, "model": model, "parallel_tool_calls": parallel_tool_calls, "previous_response_id": previous_response_id, "prompt": prompt, "prompt_cache_key": prompt_cache_key, "prompt_cache_retention": prompt_cache_retention, "reasoning": reasoning, "safety_identifier": safety_identifier, "service_tier": service_tier, "store": store, "stream": stream, "stream_options": stream_options, "temperature": temperature, "text": text, "tool_choice": tool_choice, "tools": tools, "top_logprobs": top_logprobs, "top_p": top_p, "truncation": truncation, "user": user, } ), ) ) ================================================ FILE: src/openai/resources/skills/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .skills import ( Skills, AsyncSkills, SkillsWithRawResponse, AsyncSkillsWithRawResponse, SkillsWithStreamingResponse, AsyncSkillsWithStreamingResponse, ) from .content import ( Content, AsyncContent, ContentWithRawResponse, AsyncContentWithRawResponse, ContentWithStreamingResponse, AsyncContentWithStreamingResponse, ) from .versions import ( Versions, AsyncVersions, VersionsWithRawResponse, AsyncVersionsWithRawResponse, VersionsWithStreamingResponse, AsyncVersionsWithStreamingResponse, ) __all__ = [ "Content", "AsyncContent", "ContentWithRawResponse", "AsyncContentWithRawResponse", "ContentWithStreamingResponse", "AsyncContentWithStreamingResponse", "Versions", "AsyncVersions", "VersionsWithRawResponse", "AsyncVersionsWithRawResponse", "VersionsWithStreamingResponse", "AsyncVersionsWithStreamingResponse", "Skills", "AsyncSkills", "SkillsWithRawResponse", "AsyncSkillsWithRawResponse", "SkillsWithStreamingResponse", "AsyncSkillsWithStreamingResponse", ] ================================================ FILE: src/openai/resources/skills/content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import httpx from ... import _legacy_response from ..._types import Body, Query, Headers, NotGiven, not_given from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( StreamedBinaryAPIResponse, AsyncStreamedBinaryAPIResponse, to_custom_streamed_response_wrapper, async_to_custom_streamed_response_wrapper, ) from ..._base_client import make_request_options __all__ = ["Content", "AsyncContent"] class Content(SyncAPIResource): @cached_property def with_raw_response(self) -> ContentWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return ContentWithRawResponse(self) @cached_property def with_streaming_response(self) -> ContentWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return ContentWithStreamingResponse(self) def retrieve( self, skill_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: """ Download a skill zip bundle by its ID. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not skill_id: raise ValueError(f"Expected a non-empty value for `skill_id` but received {skill_id!r}") extra_headers = {"Accept": "application/binary", **(extra_headers or {})} return self._get( f"/skills/{skill_id}/content", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=_legacy_response.HttpxBinaryResponseContent, ) class AsyncContent(AsyncAPIResource): @cached_property def with_raw_response(self) -> AsyncContentWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncContentWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncContentWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncContentWithStreamingResponse(self) async def retrieve( self, skill_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: """ Download a skill zip bundle by its ID. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not skill_id: raise ValueError(f"Expected a non-empty value for `skill_id` but received {skill_id!r}") extra_headers = {"Accept": "application/binary", **(extra_headers or {})} return await self._get( f"/skills/{skill_id}/content", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=_legacy_response.HttpxBinaryResponseContent, ) class ContentWithRawResponse: def __init__(self, content: Content) -> None: self._content = content self.retrieve = _legacy_response.to_raw_response_wrapper( content.retrieve, ) class AsyncContentWithRawResponse: def __init__(self, content: AsyncContent) -> None: self._content = content self.retrieve = _legacy_response.async_to_raw_response_wrapper( content.retrieve, ) class ContentWithStreamingResponse: def __init__(self, content: Content) -> None: self._content = content self.retrieve = to_custom_streamed_response_wrapper( content.retrieve, StreamedBinaryAPIResponse, ) class AsyncContentWithStreamingResponse: def __init__(self, content: AsyncContent) -> None: self._content = content self.retrieve = async_to_custom_streamed_response_wrapper( content.retrieve, AsyncStreamedBinaryAPIResponse, ) ================================================ FILE: src/openai/resources/skills/skills.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Mapping, cast from typing_extensions import Literal import httpx from ... import _legacy_response from ...types import skill_list_params, skill_create_params, skill_update_params from .content import ( Content, AsyncContent, ContentWithRawResponse, AsyncContentWithRawResponse, ContentWithStreamingResponse, AsyncContentWithStreamingResponse, ) from ..._types import ( Body, Omit, Query, Headers, NotGiven, FileTypes, SequenceNotStr, omit, not_given, ) from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ...pagination import SyncCursorPage, AsyncCursorPage from ...types.skill import Skill from ..._base_client import AsyncPaginator, make_request_options from .versions.versions import ( Versions, AsyncVersions, VersionsWithRawResponse, AsyncVersionsWithRawResponse, VersionsWithStreamingResponse, AsyncVersionsWithStreamingResponse, ) from ...types.deleted_skill import DeletedSkill __all__ = ["Skills", "AsyncSkills"] class Skills(SyncAPIResource): @cached_property def content(self) -> Content: return Content(self._client) @cached_property def versions(self) -> Versions: return Versions(self._client) @cached_property def with_raw_response(self) -> SkillsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return SkillsWithRawResponse(self) @cached_property def with_streaming_response(self) -> SkillsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return SkillsWithStreamingResponse(self) def create( self, *, files: Union[SequenceNotStr[FileTypes], FileTypes] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Skill: """ Create a new skill. Args: files: Skill files to upload (directory upload) or a single zip file. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ body = deepcopy_minimal({"files": files}) extracted_files = extract_files(cast(Mapping[str, object], body), paths=[["files", ""], ["files"]]) if extracted_files: # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return self._post( "/skills", body=maybe_transform(body, skill_create_params.SkillCreateParams), files=extracted_files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Skill, ) def retrieve( self, skill_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Skill: """ Get a skill by its ID. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not skill_id: raise ValueError(f"Expected a non-empty value for `skill_id` but received {skill_id!r}") return self._get( f"/skills/{skill_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Skill, ) def update( self, skill_id: str, *, default_version: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Skill: """ Update the default version pointer for a skill. Args: default_version: The skill version number to set as default. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not skill_id: raise ValueError(f"Expected a non-empty value for `skill_id` but received {skill_id!r}") return self._post( f"/skills/{skill_id}", body=maybe_transform({"default_version": default_version}, skill_update_params.SkillUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Skill, ) def list( self, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[Skill]: """ List all skills for the current project. Args: after: Identifier for the last item from the previous pagination request limit: Number of items to retrieve order: Sort order of results by timestamp. Use `asc` for ascending order or `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._get_api_list( "/skills", page=SyncCursorPage[Skill], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, }, skill_list_params.SkillListParams, ), ), model=Skill, ) def delete( self, skill_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> DeletedSkill: """ Delete a skill by its ID. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not skill_id: raise ValueError(f"Expected a non-empty value for `skill_id` but received {skill_id!r}") return self._delete( f"/skills/{skill_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=DeletedSkill, ) class AsyncSkills(AsyncAPIResource): @cached_property def content(self) -> AsyncContent: return AsyncContent(self._client) @cached_property def versions(self) -> AsyncVersions: return AsyncVersions(self._client) @cached_property def with_raw_response(self) -> AsyncSkillsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncSkillsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncSkillsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncSkillsWithStreamingResponse(self) async def create( self, *, files: Union[SequenceNotStr[FileTypes], FileTypes] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Skill: """ Create a new skill. Args: files: Skill files to upload (directory upload) or a single zip file. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ body = deepcopy_minimal({"files": files}) extracted_files = extract_files(cast(Mapping[str, object], body), paths=[["files", ""], ["files"]]) if extracted_files: # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return await self._post( "/skills", body=await async_maybe_transform(body, skill_create_params.SkillCreateParams), files=extracted_files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Skill, ) async def retrieve( self, skill_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Skill: """ Get a skill by its ID. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not skill_id: raise ValueError(f"Expected a non-empty value for `skill_id` but received {skill_id!r}") return await self._get( f"/skills/{skill_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Skill, ) async def update( self, skill_id: str, *, default_version: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Skill: """ Update the default version pointer for a skill. Args: default_version: The skill version number to set as default. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not skill_id: raise ValueError(f"Expected a non-empty value for `skill_id` but received {skill_id!r}") return await self._post( f"/skills/{skill_id}", body=await async_maybe_transform( {"default_version": default_version}, skill_update_params.SkillUpdateParams ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Skill, ) def list( self, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[Skill, AsyncCursorPage[Skill]]: """ List all skills for the current project. Args: after: Identifier for the last item from the previous pagination request limit: Number of items to retrieve order: Sort order of results by timestamp. Use `asc` for ascending order or `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._get_api_list( "/skills", page=AsyncCursorPage[Skill], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, }, skill_list_params.SkillListParams, ), ), model=Skill, ) async def delete( self, skill_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> DeletedSkill: """ Delete a skill by its ID. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not skill_id: raise ValueError(f"Expected a non-empty value for `skill_id` but received {skill_id!r}") return await self._delete( f"/skills/{skill_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=DeletedSkill, ) class SkillsWithRawResponse: def __init__(self, skills: Skills) -> None: self._skills = skills self.create = _legacy_response.to_raw_response_wrapper( skills.create, ) self.retrieve = _legacy_response.to_raw_response_wrapper( skills.retrieve, ) self.update = _legacy_response.to_raw_response_wrapper( skills.update, ) self.list = _legacy_response.to_raw_response_wrapper( skills.list, ) self.delete = _legacy_response.to_raw_response_wrapper( skills.delete, ) @cached_property def content(self) -> ContentWithRawResponse: return ContentWithRawResponse(self._skills.content) @cached_property def versions(self) -> VersionsWithRawResponse: return VersionsWithRawResponse(self._skills.versions) class AsyncSkillsWithRawResponse: def __init__(self, skills: AsyncSkills) -> None: self._skills = skills self.create = _legacy_response.async_to_raw_response_wrapper( skills.create, ) self.retrieve = _legacy_response.async_to_raw_response_wrapper( skills.retrieve, ) self.update = _legacy_response.async_to_raw_response_wrapper( skills.update, ) self.list = _legacy_response.async_to_raw_response_wrapper( skills.list, ) self.delete = _legacy_response.async_to_raw_response_wrapper( skills.delete, ) @cached_property def content(self) -> AsyncContentWithRawResponse: return AsyncContentWithRawResponse(self._skills.content) @cached_property def versions(self) -> AsyncVersionsWithRawResponse: return AsyncVersionsWithRawResponse(self._skills.versions) class SkillsWithStreamingResponse: def __init__(self, skills: Skills) -> None: self._skills = skills self.create = to_streamed_response_wrapper( skills.create, ) self.retrieve = to_streamed_response_wrapper( skills.retrieve, ) self.update = to_streamed_response_wrapper( skills.update, ) self.list = to_streamed_response_wrapper( skills.list, ) self.delete = to_streamed_response_wrapper( skills.delete, ) @cached_property def content(self) -> ContentWithStreamingResponse: return ContentWithStreamingResponse(self._skills.content) @cached_property def versions(self) -> VersionsWithStreamingResponse: return VersionsWithStreamingResponse(self._skills.versions) class AsyncSkillsWithStreamingResponse: def __init__(self, skills: AsyncSkills) -> None: self._skills = skills self.create = async_to_streamed_response_wrapper( skills.create, ) self.retrieve = async_to_streamed_response_wrapper( skills.retrieve, ) self.update = async_to_streamed_response_wrapper( skills.update, ) self.list = async_to_streamed_response_wrapper( skills.list, ) self.delete = async_to_streamed_response_wrapper( skills.delete, ) @cached_property def content(self) -> AsyncContentWithStreamingResponse: return AsyncContentWithStreamingResponse(self._skills.content) @cached_property def versions(self) -> AsyncVersionsWithStreamingResponse: return AsyncVersionsWithStreamingResponse(self._skills.versions) ================================================ FILE: src/openai/resources/skills/versions/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .content import ( Content, AsyncContent, ContentWithRawResponse, AsyncContentWithRawResponse, ContentWithStreamingResponse, AsyncContentWithStreamingResponse, ) from .versions import ( Versions, AsyncVersions, VersionsWithRawResponse, AsyncVersionsWithRawResponse, VersionsWithStreamingResponse, AsyncVersionsWithStreamingResponse, ) __all__ = [ "Content", "AsyncContent", "ContentWithRawResponse", "AsyncContentWithRawResponse", "ContentWithStreamingResponse", "AsyncContentWithStreamingResponse", "Versions", "AsyncVersions", "VersionsWithRawResponse", "AsyncVersionsWithRawResponse", "VersionsWithStreamingResponse", "AsyncVersionsWithStreamingResponse", ] ================================================ FILE: src/openai/resources/skills/versions/content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import httpx from .... import _legacy_response from ...._types import Body, Query, Headers, NotGiven, not_given from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import ( StreamedBinaryAPIResponse, AsyncStreamedBinaryAPIResponse, to_custom_streamed_response_wrapper, async_to_custom_streamed_response_wrapper, ) from ...._base_client import make_request_options __all__ = ["Content", "AsyncContent"] class Content(SyncAPIResource): @cached_property def with_raw_response(self) -> ContentWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return ContentWithRawResponse(self) @cached_property def with_streaming_response(self) -> ContentWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return ContentWithStreamingResponse(self) def retrieve( self, version: str, *, skill_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: """ Download a skill version zip bundle. Args: version: The skill version number. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not skill_id: raise ValueError(f"Expected a non-empty value for `skill_id` but received {skill_id!r}") if not version: raise ValueError(f"Expected a non-empty value for `version` but received {version!r}") extra_headers = {"Accept": "application/binary", **(extra_headers or {})} return self._get( f"/skills/{skill_id}/versions/{version}/content", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=_legacy_response.HttpxBinaryResponseContent, ) class AsyncContent(AsyncAPIResource): @cached_property def with_raw_response(self) -> AsyncContentWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncContentWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncContentWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncContentWithStreamingResponse(self) async def retrieve( self, version: str, *, skill_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: """ Download a skill version zip bundle. Args: version: The skill version number. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not skill_id: raise ValueError(f"Expected a non-empty value for `skill_id` but received {skill_id!r}") if not version: raise ValueError(f"Expected a non-empty value for `version` but received {version!r}") extra_headers = {"Accept": "application/binary", **(extra_headers or {})} return await self._get( f"/skills/{skill_id}/versions/{version}/content", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=_legacy_response.HttpxBinaryResponseContent, ) class ContentWithRawResponse: def __init__(self, content: Content) -> None: self._content = content self.retrieve = _legacy_response.to_raw_response_wrapper( content.retrieve, ) class AsyncContentWithRawResponse: def __init__(self, content: AsyncContent) -> None: self._content = content self.retrieve = _legacy_response.async_to_raw_response_wrapper( content.retrieve, ) class ContentWithStreamingResponse: def __init__(self, content: Content) -> None: self._content = content self.retrieve = to_custom_streamed_response_wrapper( content.retrieve, StreamedBinaryAPIResponse, ) class AsyncContentWithStreamingResponse: def __init__(self, content: AsyncContent) -> None: self._content = content self.retrieve = async_to_custom_streamed_response_wrapper( content.retrieve, AsyncStreamedBinaryAPIResponse, ) ================================================ FILE: src/openai/resources/skills/versions/versions.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Mapping, cast from typing_extensions import Literal import httpx from .... import _legacy_response from .content import ( Content, AsyncContent, ContentWithRawResponse, AsyncContentWithRawResponse, ContentWithStreamingResponse, AsyncContentWithStreamingResponse, ) from ...._types import ( Body, Omit, Query, Headers, NotGiven, FileTypes, SequenceNotStr, omit, not_given, ) from ...._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ....pagination import SyncCursorPage, AsyncCursorPage from ...._base_client import AsyncPaginator, make_request_options from ....types.skills import version_list_params, version_create_params from ....types.skills.skill_version import SkillVersion from ....types.skills.deleted_skill_version import DeletedSkillVersion __all__ = ["Versions", "AsyncVersions"] class Versions(SyncAPIResource): @cached_property def content(self) -> Content: return Content(self._client) @cached_property def with_raw_response(self) -> VersionsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return VersionsWithRawResponse(self) @cached_property def with_streaming_response(self) -> VersionsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return VersionsWithStreamingResponse(self) def create( self, skill_id: str, *, default: bool | Omit = omit, files: Union[SequenceNotStr[FileTypes], FileTypes] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SkillVersion: """ Create a new immutable skill version. Args: default: Whether to set this version as the default. files: Skill files to upload (directory upload) or a single zip file. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not skill_id: raise ValueError(f"Expected a non-empty value for `skill_id` but received {skill_id!r}") body = deepcopy_minimal( { "default": default, "files": files, } ) extracted_files = extract_files(cast(Mapping[str, object], body), paths=[["files", ""], ["files"]]) if extracted_files: # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return self._post( f"/skills/{skill_id}/versions", body=maybe_transform(body, version_create_params.VersionCreateParams), files=extracted_files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=SkillVersion, ) def retrieve( self, version: str, *, skill_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SkillVersion: """ Get a specific skill version. Args: version: The version number to retrieve. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not skill_id: raise ValueError(f"Expected a non-empty value for `skill_id` but received {skill_id!r}") if not version: raise ValueError(f"Expected a non-empty value for `version` but received {version!r}") return self._get( f"/skills/{skill_id}/versions/{version}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=SkillVersion, ) def list( self, skill_id: str, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[SkillVersion]: """ List skill versions for a skill. Args: after: The skill version ID to start after. limit: Number of versions to retrieve. order: Sort order of results by version number. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not skill_id: raise ValueError(f"Expected a non-empty value for `skill_id` but received {skill_id!r}") return self._get_api_list( f"/skills/{skill_id}/versions", page=SyncCursorPage[SkillVersion], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, }, version_list_params.VersionListParams, ), ), model=SkillVersion, ) def delete( self, version: str, *, skill_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> DeletedSkillVersion: """ Delete a skill version. Args: version: The skill version number. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not skill_id: raise ValueError(f"Expected a non-empty value for `skill_id` but received {skill_id!r}") if not version: raise ValueError(f"Expected a non-empty value for `version` but received {version!r}") return self._delete( f"/skills/{skill_id}/versions/{version}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=DeletedSkillVersion, ) class AsyncVersions(AsyncAPIResource): @cached_property def content(self) -> AsyncContent: return AsyncContent(self._client) @cached_property def with_raw_response(self) -> AsyncVersionsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncVersionsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncVersionsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncVersionsWithStreamingResponse(self) async def create( self, skill_id: str, *, default: bool | Omit = omit, files: Union[SequenceNotStr[FileTypes], FileTypes] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SkillVersion: """ Create a new immutable skill version. Args: default: Whether to set this version as the default. files: Skill files to upload (directory upload) or a single zip file. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not skill_id: raise ValueError(f"Expected a non-empty value for `skill_id` but received {skill_id!r}") body = deepcopy_minimal( { "default": default, "files": files, } ) extracted_files = extract_files(cast(Mapping[str, object], body), paths=[["files", ""], ["files"]]) if extracted_files: # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return await self._post( f"/skills/{skill_id}/versions", body=await async_maybe_transform(body, version_create_params.VersionCreateParams), files=extracted_files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=SkillVersion, ) async def retrieve( self, version: str, *, skill_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SkillVersion: """ Get a specific skill version. Args: version: The version number to retrieve. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not skill_id: raise ValueError(f"Expected a non-empty value for `skill_id` but received {skill_id!r}") if not version: raise ValueError(f"Expected a non-empty value for `version` but received {version!r}") return await self._get( f"/skills/{skill_id}/versions/{version}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=SkillVersion, ) def list( self, skill_id: str, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[SkillVersion, AsyncCursorPage[SkillVersion]]: """ List skill versions for a skill. Args: after: The skill version ID to start after. limit: Number of versions to retrieve. order: Sort order of results by version number. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not skill_id: raise ValueError(f"Expected a non-empty value for `skill_id` but received {skill_id!r}") return self._get_api_list( f"/skills/{skill_id}/versions", page=AsyncCursorPage[SkillVersion], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, }, version_list_params.VersionListParams, ), ), model=SkillVersion, ) async def delete( self, version: str, *, skill_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> DeletedSkillVersion: """ Delete a skill version. Args: version: The skill version number. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not skill_id: raise ValueError(f"Expected a non-empty value for `skill_id` but received {skill_id!r}") if not version: raise ValueError(f"Expected a non-empty value for `version` but received {version!r}") return await self._delete( f"/skills/{skill_id}/versions/{version}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=DeletedSkillVersion, ) class VersionsWithRawResponse: def __init__(self, versions: Versions) -> None: self._versions = versions self.create = _legacy_response.to_raw_response_wrapper( versions.create, ) self.retrieve = _legacy_response.to_raw_response_wrapper( versions.retrieve, ) self.list = _legacy_response.to_raw_response_wrapper( versions.list, ) self.delete = _legacy_response.to_raw_response_wrapper( versions.delete, ) @cached_property def content(self) -> ContentWithRawResponse: return ContentWithRawResponse(self._versions.content) class AsyncVersionsWithRawResponse: def __init__(self, versions: AsyncVersions) -> None: self._versions = versions self.create = _legacy_response.async_to_raw_response_wrapper( versions.create, ) self.retrieve = _legacy_response.async_to_raw_response_wrapper( versions.retrieve, ) self.list = _legacy_response.async_to_raw_response_wrapper( versions.list, ) self.delete = _legacy_response.async_to_raw_response_wrapper( versions.delete, ) @cached_property def content(self) -> AsyncContentWithRawResponse: return AsyncContentWithRawResponse(self._versions.content) class VersionsWithStreamingResponse: def __init__(self, versions: Versions) -> None: self._versions = versions self.create = to_streamed_response_wrapper( versions.create, ) self.retrieve = to_streamed_response_wrapper( versions.retrieve, ) self.list = to_streamed_response_wrapper( versions.list, ) self.delete = to_streamed_response_wrapper( versions.delete, ) @cached_property def content(self) -> ContentWithStreamingResponse: return ContentWithStreamingResponse(self._versions.content) class AsyncVersionsWithStreamingResponse: def __init__(self, versions: AsyncVersions) -> None: self._versions = versions self.create = async_to_streamed_response_wrapper( versions.create, ) self.retrieve = async_to_streamed_response_wrapper( versions.retrieve, ) self.list = async_to_streamed_response_wrapper( versions.list, ) self.delete = async_to_streamed_response_wrapper( versions.delete, ) @cached_property def content(self) -> AsyncContentWithStreamingResponse: return AsyncContentWithStreamingResponse(self._versions.content) ================================================ FILE: src/openai/resources/uploads/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .parts import ( Parts, AsyncParts, PartsWithRawResponse, AsyncPartsWithRawResponse, PartsWithStreamingResponse, AsyncPartsWithStreamingResponse, ) from .uploads import ( Uploads, AsyncUploads, UploadsWithRawResponse, AsyncUploadsWithRawResponse, UploadsWithStreamingResponse, AsyncUploadsWithStreamingResponse, ) __all__ = [ "Parts", "AsyncParts", "PartsWithRawResponse", "AsyncPartsWithRawResponse", "PartsWithStreamingResponse", "AsyncPartsWithStreamingResponse", "Uploads", "AsyncUploads", "UploadsWithRawResponse", "AsyncUploadsWithRawResponse", "UploadsWithStreamingResponse", "AsyncUploadsWithStreamingResponse", ] ================================================ FILE: src/openai/resources/uploads/parts.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Mapping, cast import httpx from ... import _legacy_response from ..._types import Body, Query, Headers, NotGiven, FileTypes, not_given from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ..._base_client import make_request_options from ...types.uploads import part_create_params from ...types.uploads.upload_part import UploadPart __all__ = ["Parts", "AsyncParts"] class Parts(SyncAPIResource): """Use Uploads to upload large files in multiple parts.""" @cached_property def with_raw_response(self) -> PartsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return PartsWithRawResponse(self) @cached_property def with_streaming_response(self) -> PartsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return PartsWithStreamingResponse(self) def create( self, upload_id: str, *, data: FileTypes, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> UploadPart: """ Adds a [Part](https://platform.openai.com/docs/api-reference/uploads/part-object) to an [Upload](https://platform.openai.com/docs/api-reference/uploads/object) object. A Part represents a chunk of bytes from the file you are trying to upload. Each Part can be at most 64 MB, and you can add Parts until you hit the Upload maximum of 8 GB. It is possible to add multiple Parts in parallel. You can decide the intended order of the Parts when you [complete the Upload](https://platform.openai.com/docs/api-reference/uploads/complete). Args: data: The chunk of bytes for this Part. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not upload_id: raise ValueError(f"Expected a non-empty value for `upload_id` but received {upload_id!r}") body = deepcopy_minimal({"data": data}) files = extract_files(cast(Mapping[str, object], body), paths=[["data"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return self._post( f"/uploads/{upload_id}/parts", body=maybe_transform(body, part_create_params.PartCreateParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=UploadPart, ) class AsyncParts(AsyncAPIResource): """Use Uploads to upload large files in multiple parts.""" @cached_property def with_raw_response(self) -> AsyncPartsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncPartsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncPartsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncPartsWithStreamingResponse(self) async def create( self, upload_id: str, *, data: FileTypes, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> UploadPart: """ Adds a [Part](https://platform.openai.com/docs/api-reference/uploads/part-object) to an [Upload](https://platform.openai.com/docs/api-reference/uploads/object) object. A Part represents a chunk of bytes from the file you are trying to upload. Each Part can be at most 64 MB, and you can add Parts until you hit the Upload maximum of 8 GB. It is possible to add multiple Parts in parallel. You can decide the intended order of the Parts when you [complete the Upload](https://platform.openai.com/docs/api-reference/uploads/complete). Args: data: The chunk of bytes for this Part. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not upload_id: raise ValueError(f"Expected a non-empty value for `upload_id` but received {upload_id!r}") body = deepcopy_minimal({"data": data}) files = extract_files(cast(Mapping[str, object], body), paths=[["data"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return await self._post( f"/uploads/{upload_id}/parts", body=await async_maybe_transform(body, part_create_params.PartCreateParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=UploadPart, ) class PartsWithRawResponse: def __init__(self, parts: Parts) -> None: self._parts = parts self.create = _legacy_response.to_raw_response_wrapper( parts.create, ) class AsyncPartsWithRawResponse: def __init__(self, parts: AsyncParts) -> None: self._parts = parts self.create = _legacy_response.async_to_raw_response_wrapper( parts.create, ) class PartsWithStreamingResponse: def __init__(self, parts: Parts) -> None: self._parts = parts self.create = to_streamed_response_wrapper( parts.create, ) class AsyncPartsWithStreamingResponse: def __init__(self, parts: AsyncParts) -> None: self._parts = parts self.create = async_to_streamed_response_wrapper( parts.create, ) ================================================ FILE: src/openai/resources/uploads/uploads.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import io import os import logging import builtins from typing import overload from pathlib import Path import anyio import httpx from ... import _legacy_response from .parts import ( Parts, AsyncParts, PartsWithRawResponse, AsyncPartsWithRawResponse, PartsWithStreamingResponse, AsyncPartsWithStreamingResponse, ) from ...types import FilePurpose, upload_create_params, upload_complete_params from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ..._base_client import make_request_options from ...types.upload import Upload from ...types.file_purpose import FilePurpose __all__ = ["Uploads", "AsyncUploads"] # 64MB DEFAULT_PART_SIZE = 64 * 1024 * 1024 log: logging.Logger = logging.getLogger(__name__) class Uploads(SyncAPIResource): """Use Uploads to upload large files in multiple parts.""" @cached_property def parts(self) -> Parts: """Use Uploads to upload large files in multiple parts.""" return Parts(self._client) @cached_property def with_raw_response(self) -> UploadsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return UploadsWithRawResponse(self) @cached_property def with_streaming_response(self) -> UploadsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return UploadsWithStreamingResponse(self) @overload def upload_file_chunked( self, *, file: os.PathLike[str], mime_type: str, purpose: FilePurpose, bytes: int | None = None, part_size: int | None = None, md5: str | Omit = omit, ) -> Upload: """Splits a file into multiple 64MB parts and uploads them sequentially.""" @overload def upload_file_chunked( self, *, file: bytes, filename: str, bytes: int, mime_type: str, purpose: FilePurpose, part_size: int | None = None, md5: str | Omit = omit, ) -> Upload: """Splits an in-memory file into multiple 64MB parts and uploads them sequentially.""" def upload_file_chunked( self, *, file: os.PathLike[str] | bytes, mime_type: str, purpose: FilePurpose, filename: str | None = None, bytes: int | None = None, part_size: int | None = None, md5: str | Omit = omit, ) -> Upload: """Splits the given file into multiple parts and uploads them sequentially. ```py from pathlib import Path client.uploads.upload_file( file=Path("my-paper.pdf"), mime_type="pdf", purpose="assistants", ) ``` """ if isinstance(file, builtins.bytes): if filename is None: raise TypeError("The `filename` argument must be given for in-memory files") if bytes is None: raise TypeError("The `bytes` argument must be given for in-memory files") else: if not isinstance(file, Path): file = Path(file) if not filename: filename = file.name if bytes is None: bytes = file.stat().st_size upload = self.create( bytes=bytes, filename=filename, mime_type=mime_type, purpose=purpose, ) part_ids: list[str] = [] if part_size is None: part_size = DEFAULT_PART_SIZE if isinstance(file, builtins.bytes): buf: io.FileIO | io.BytesIO = io.BytesIO(file) else: buf = io.FileIO(file) try: while True: data = buf.read(part_size) if not data: # EOF break part = self.parts.create(upload_id=upload.id, data=data) log.info("Uploaded part %s for upload %s", part.id, upload.id) part_ids.append(part.id) finally: buf.close() return self.complete(upload_id=upload.id, part_ids=part_ids, md5=md5) def create( self, *, bytes: int, filename: str, mime_type: str, purpose: FilePurpose, expires_after: upload_create_params.ExpiresAfter | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Upload: """ Creates an intermediate [Upload](https://platform.openai.com/docs/api-reference/uploads/object) object that you can add [Parts](https://platform.openai.com/docs/api-reference/uploads/part-object) to. Currently, an Upload can accept at most 8 GB in total and expires after an hour after you create it. Once you complete the Upload, we will create a [File](https://platform.openai.com/docs/api-reference/files/object) object that contains all the parts you uploaded. This File is usable in the rest of our platform as a regular File object. For certain `purpose` values, the correct `mime_type` must be specified. Please refer to documentation for the [supported MIME types for your use case](https://platform.openai.com/docs/assistants/tools/file-search#supported-files). For guidance on the proper filename extensions for each purpose, please follow the documentation on [creating a File](https://platform.openai.com/docs/api-reference/files/create). Returns the Upload object with status `pending`. Args: bytes: The number of bytes in the file you are uploading. filename: The name of the file to upload. mime_type: The MIME type of the file. This must fall within the supported MIME types for your file purpose. See the supported MIME types for assistants and vision. purpose: The intended purpose of the uploaded file. See the [documentation on File purposes](https://platform.openai.com/docs/api-reference/files/create#files-create-purpose). expires_after: The expiration policy for a file. By default, files with `purpose=batch` expire after 30 days and all other files are persisted until they are manually deleted. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._post( "/uploads", body=maybe_transform( { "bytes": bytes, "filename": filename, "mime_type": mime_type, "purpose": purpose, "expires_after": expires_after, }, upload_create_params.UploadCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Upload, ) def cancel( self, upload_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Upload: """Cancels the Upload. No Parts may be added after an Upload is cancelled. Returns the Upload object with status `cancelled`. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not upload_id: raise ValueError(f"Expected a non-empty value for `upload_id` but received {upload_id!r}") return self._post( f"/uploads/{upload_id}/cancel", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Upload, ) def complete( self, upload_id: str, *, part_ids: SequenceNotStr[str], md5: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Upload: """ Completes the [Upload](https://platform.openai.com/docs/api-reference/uploads/object). Within the returned Upload object, there is a nested [File](https://platform.openai.com/docs/api-reference/files/object) object that is ready to use in the rest of the platform. You can specify the order of the Parts by passing in an ordered list of the Part IDs. The number of bytes uploaded upon completion must match the number of bytes initially specified when creating the Upload object. No Parts may be added after an Upload is completed. Returns the Upload object with status `completed`, including an additional `file` property containing the created usable File object. Args: part_ids: The ordered list of Part IDs. md5: The optional md5 checksum for the file contents to verify if the bytes uploaded matches what you expect. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not upload_id: raise ValueError(f"Expected a non-empty value for `upload_id` but received {upload_id!r}") return self._post( f"/uploads/{upload_id}/complete", body=maybe_transform( { "part_ids": part_ids, "md5": md5, }, upload_complete_params.UploadCompleteParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Upload, ) class AsyncUploads(AsyncAPIResource): """Use Uploads to upload large files in multiple parts.""" @cached_property def parts(self) -> AsyncParts: """Use Uploads to upload large files in multiple parts.""" return AsyncParts(self._client) @cached_property def with_raw_response(self) -> AsyncUploadsWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncUploadsWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncUploadsWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncUploadsWithStreamingResponse(self) @overload async def upload_file_chunked( self, *, file: os.PathLike[str], mime_type: str, purpose: FilePurpose, bytes: int | None = None, part_size: int | None = None, md5: str | Omit = omit, ) -> Upload: """Splits a file into multiple 64MB parts and uploads them sequentially.""" @overload async def upload_file_chunked( self, *, file: bytes, filename: str, bytes: int, mime_type: str, purpose: FilePurpose, part_size: int | None = None, md5: str | Omit = omit, ) -> Upload: """Splits an in-memory file into multiple 64MB parts and uploads them sequentially.""" async def upload_file_chunked( self, *, file: os.PathLike[str] | bytes, mime_type: str, purpose: FilePurpose, filename: str | None = None, bytes: int | None = None, part_size: int | None = None, md5: str | Omit = omit, ) -> Upload: """Splits the given file into multiple parts and uploads them sequentially. ```py from pathlib import Path client.uploads.upload_file( file=Path("my-paper.pdf"), mime_type="pdf", purpose="assistants", ) ``` """ if isinstance(file, builtins.bytes): if filename is None: raise TypeError("The `filename` argument must be given for in-memory files") if bytes is None: raise TypeError("The `bytes` argument must be given for in-memory files") else: if not isinstance(file, anyio.Path): file = anyio.Path(file) if not filename: filename = file.name if bytes is None: stat = await file.stat() bytes = stat.st_size upload = await self.create( bytes=bytes, filename=filename, mime_type=mime_type, purpose=purpose, ) part_ids: list[str] = [] if part_size is None: part_size = DEFAULT_PART_SIZE if isinstance(file, anyio.Path): fd = await file.open("rb") async with fd: while True: data = await fd.read(part_size) if not data: # EOF break part = await self.parts.create(upload_id=upload.id, data=data) log.info("Uploaded part %s for upload %s", part.id, upload.id) part_ids.append(part.id) else: buf = io.BytesIO(file) try: while True: data = buf.read(part_size) if not data: # EOF break part = await self.parts.create(upload_id=upload.id, data=data) log.info("Uploaded part %s for upload %s", part.id, upload.id) part_ids.append(part.id) finally: buf.close() return await self.complete(upload_id=upload.id, part_ids=part_ids, md5=md5) async def create( self, *, bytes: int, filename: str, mime_type: str, purpose: FilePurpose, expires_after: upload_create_params.ExpiresAfter | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Upload: """ Creates an intermediate [Upload](https://platform.openai.com/docs/api-reference/uploads/object) object that you can add [Parts](https://platform.openai.com/docs/api-reference/uploads/part-object) to. Currently, an Upload can accept at most 8 GB in total and expires after an hour after you create it. Once you complete the Upload, we will create a [File](https://platform.openai.com/docs/api-reference/files/object) object that contains all the parts you uploaded. This File is usable in the rest of our platform as a regular File object. For certain `purpose` values, the correct `mime_type` must be specified. Please refer to documentation for the [supported MIME types for your use case](https://platform.openai.com/docs/assistants/tools/file-search#supported-files). For guidance on the proper filename extensions for each purpose, please follow the documentation on [creating a File](https://platform.openai.com/docs/api-reference/files/create). Returns the Upload object with status `pending`. Args: bytes: The number of bytes in the file you are uploading. filename: The name of the file to upload. mime_type: The MIME type of the file. This must fall within the supported MIME types for your file purpose. See the supported MIME types for assistants and vision. purpose: The intended purpose of the uploaded file. See the [documentation on File purposes](https://platform.openai.com/docs/api-reference/files/create#files-create-purpose). expires_after: The expiration policy for a file. By default, files with `purpose=batch` expire after 30 days and all other files are persisted until they are manually deleted. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return await self._post( "/uploads", body=await async_maybe_transform( { "bytes": bytes, "filename": filename, "mime_type": mime_type, "purpose": purpose, "expires_after": expires_after, }, upload_create_params.UploadCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Upload, ) async def cancel( self, upload_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Upload: """Cancels the Upload. No Parts may be added after an Upload is cancelled. Returns the Upload object with status `cancelled`. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not upload_id: raise ValueError(f"Expected a non-empty value for `upload_id` but received {upload_id!r}") return await self._post( f"/uploads/{upload_id}/cancel", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Upload, ) async def complete( self, upload_id: str, *, part_ids: SequenceNotStr[str], md5: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Upload: """ Completes the [Upload](https://platform.openai.com/docs/api-reference/uploads/object). Within the returned Upload object, there is a nested [File](https://platform.openai.com/docs/api-reference/files/object) object that is ready to use in the rest of the platform. You can specify the order of the Parts by passing in an ordered list of the Part IDs. The number of bytes uploaded upon completion must match the number of bytes initially specified when creating the Upload object. No Parts may be added after an Upload is completed. Returns the Upload object with status `completed`, including an additional `file` property containing the created usable File object. Args: part_ids: The ordered list of Part IDs. md5: The optional md5 checksum for the file contents to verify if the bytes uploaded matches what you expect. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not upload_id: raise ValueError(f"Expected a non-empty value for `upload_id` but received {upload_id!r}") return await self._post( f"/uploads/{upload_id}/complete", body=await async_maybe_transform( { "part_ids": part_ids, "md5": md5, }, upload_complete_params.UploadCompleteParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Upload, ) class UploadsWithRawResponse: def __init__(self, uploads: Uploads) -> None: self._uploads = uploads self.create = _legacy_response.to_raw_response_wrapper( uploads.create, ) self.cancel = _legacy_response.to_raw_response_wrapper( uploads.cancel, ) self.complete = _legacy_response.to_raw_response_wrapper( uploads.complete, ) @cached_property def parts(self) -> PartsWithRawResponse: """Use Uploads to upload large files in multiple parts.""" return PartsWithRawResponse(self._uploads.parts) class AsyncUploadsWithRawResponse: def __init__(self, uploads: AsyncUploads) -> None: self._uploads = uploads self.create = _legacy_response.async_to_raw_response_wrapper( uploads.create, ) self.cancel = _legacy_response.async_to_raw_response_wrapper( uploads.cancel, ) self.complete = _legacy_response.async_to_raw_response_wrapper( uploads.complete, ) @cached_property def parts(self) -> AsyncPartsWithRawResponse: """Use Uploads to upload large files in multiple parts.""" return AsyncPartsWithRawResponse(self._uploads.parts) class UploadsWithStreamingResponse: def __init__(self, uploads: Uploads) -> None: self._uploads = uploads self.create = to_streamed_response_wrapper( uploads.create, ) self.cancel = to_streamed_response_wrapper( uploads.cancel, ) self.complete = to_streamed_response_wrapper( uploads.complete, ) @cached_property def parts(self) -> PartsWithStreamingResponse: """Use Uploads to upload large files in multiple parts.""" return PartsWithStreamingResponse(self._uploads.parts) class AsyncUploadsWithStreamingResponse: def __init__(self, uploads: AsyncUploads) -> None: self._uploads = uploads self.create = async_to_streamed_response_wrapper( uploads.create, ) self.cancel = async_to_streamed_response_wrapper( uploads.cancel, ) self.complete = async_to_streamed_response_wrapper( uploads.complete, ) @cached_property def parts(self) -> AsyncPartsWithStreamingResponse: """Use Uploads to upload large files in multiple parts.""" return AsyncPartsWithStreamingResponse(self._uploads.parts) ================================================ FILE: src/openai/resources/vector_stores/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .files import ( Files, AsyncFiles, FilesWithRawResponse, AsyncFilesWithRawResponse, FilesWithStreamingResponse, AsyncFilesWithStreamingResponse, ) from .file_batches import ( FileBatches, AsyncFileBatches, FileBatchesWithRawResponse, AsyncFileBatchesWithRawResponse, FileBatchesWithStreamingResponse, AsyncFileBatchesWithStreamingResponse, ) from .vector_stores import ( VectorStores, AsyncVectorStores, VectorStoresWithRawResponse, AsyncVectorStoresWithRawResponse, VectorStoresWithStreamingResponse, AsyncVectorStoresWithStreamingResponse, ) __all__ = [ "Files", "AsyncFiles", "FilesWithRawResponse", "AsyncFilesWithRawResponse", "FilesWithStreamingResponse", "AsyncFilesWithStreamingResponse", "FileBatches", "AsyncFileBatches", "FileBatchesWithRawResponse", "AsyncFileBatchesWithRawResponse", "FileBatchesWithStreamingResponse", "AsyncFileBatchesWithStreamingResponse", "VectorStores", "AsyncVectorStores", "VectorStoresWithRawResponse", "AsyncVectorStoresWithRawResponse", "VectorStoresWithStreamingResponse", "AsyncVectorStoresWithStreamingResponse", ] ================================================ FILE: src/openai/resources/vector_stores/file_batches.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import asyncio from typing import Dict, Iterable, Optional from typing_extensions import Union, Literal from concurrent.futures import Future, ThreadPoolExecutor, as_completed import httpx import sniffio from ... import _legacy_response from ...types import FileChunkingStrategyParam from ..._types import Body, Omit, Query, Headers, NotGiven, FileTypes, SequenceNotStr, omit, not_given from ..._utils import is_given, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ...pagination import SyncCursorPage, AsyncCursorPage from ..._base_client import AsyncPaginator, make_request_options from ...types.file_object import FileObject from ...types.vector_stores import file_batch_create_params, file_batch_list_files_params from ...types.file_chunking_strategy_param import FileChunkingStrategyParam from ...types.vector_stores.vector_store_file import VectorStoreFile from ...types.vector_stores.vector_store_file_batch import VectorStoreFileBatch __all__ = ["FileBatches", "AsyncFileBatches"] class FileBatches(SyncAPIResource): @cached_property def with_raw_response(self) -> FileBatchesWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return FileBatchesWithRawResponse(self) @cached_property def with_streaming_response(self) -> FileBatchesWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return FileBatchesWithStreamingResponse(self) def create( self, vector_store_id: str, *, attributes: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, chunking_strategy: FileChunkingStrategyParam | Omit = omit, file_ids: SequenceNotStr[str] | Omit = omit, files: Iterable[file_batch_create_params.File] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreFileBatch: """ Create a vector store file batch. Args: attributes: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters, booleans, or numbers. chunking_strategy: The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. Only applicable if `file_ids` is non-empty. file_ids: A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the vector store should use. Useful for tools like `file_search` that can access files. If `attributes` or `chunking_strategy` are provided, they will be applied to all files in the batch. The maximum batch size is 2000 files. Mutually exclusive with `files`. files: A list of objects that each include a `file_id` plus optional `attributes` or `chunking_strategy`. Use this when you need to override metadata for specific files. The global `attributes` or `chunking_strategy` will be ignored and must be specified for each file. The maximum batch size is 2000 files. Mutually exclusive with `file_ids`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._post( f"/vector_stores/{vector_store_id}/file_batches", body=maybe_transform( { "attributes": attributes, "chunking_strategy": chunking_strategy, "file_ids": file_ids, "files": files, }, file_batch_create_params.FileBatchCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStoreFileBatch, ) def retrieve( self, batch_id: str, *, vector_store_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreFileBatch: """ Retrieves a vector store file batch. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") if not batch_id: raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get( f"/vector_stores/{vector_store_id}/file_batches/{batch_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStoreFileBatch, ) def cancel( self, batch_id: str, *, vector_store_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreFileBatch: """Cancel a vector store file batch. This attempts to cancel the processing of files in this batch as soon as possible. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") if not batch_id: raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._post( f"/vector_stores/{vector_store_id}/file_batches/{batch_id}/cancel", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStoreFileBatch, ) def create_and_poll( self, vector_store_id: str, *, attributes: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, chunking_strategy: FileChunkingStrategyParam | Omit = omit, file_ids: SequenceNotStr[str] | Omit = omit, files: Iterable[file_batch_create_params.File] | Omit = omit, poll_interval_ms: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreFileBatch: """Create a vector store batch and poll until all files have been processed.""" batch = self.create( vector_store_id=vector_store_id, attributes=attributes, chunking_strategy=chunking_strategy, file_ids=file_ids, files=files, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, ) # TODO: don't poll unless necessary?? return self.poll( batch.id, vector_store_id=vector_store_id, poll_interval_ms=poll_interval_ms, ) def list_files( self, batch_id: str, *, vector_store_id: str, after: str | Omit = omit, before: str | Omit = omit, filter: Literal["in_progress", "completed", "failed", "cancelled"] | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[VectorStoreFile]: """ Returns a list of vector store files in a batch. Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. before: A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. filter: Filter by file status. One of `in_progress`, `completed`, `failed`, `cancelled`. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") if not batch_id: raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get_api_list( f"/vector_stores/{vector_store_id}/file_batches/{batch_id}/files", page=SyncCursorPage[VectorStoreFile], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "filter": filter, "limit": limit, "order": order, }, file_batch_list_files_params.FileBatchListFilesParams, ), ), model=VectorStoreFile, ) def poll( self, batch_id: str, *, vector_store_id: str, poll_interval_ms: int | Omit = omit, ) -> VectorStoreFileBatch: """Wait for the given file batch to be processed. Note: this will return even if one of the files failed to process, you need to check batch.file_counts.failed_count to handle this case. """ headers: dict[str, str] = {"X-Stainless-Poll-Helper": "true"} if is_given(poll_interval_ms): headers["X-Stainless-Custom-Poll-Interval"] = str(poll_interval_ms) while True: response = self.with_raw_response.retrieve( batch_id, vector_store_id=vector_store_id, extra_headers=headers, ) batch = response.parse() if batch.file_counts.in_progress > 0: if not is_given(poll_interval_ms): from_header = response.headers.get("openai-poll-after-ms") if from_header is not None: poll_interval_ms = int(from_header) else: poll_interval_ms = 1000 self._sleep(poll_interval_ms / 1000) continue return batch def upload_and_poll( self, vector_store_id: str, *, files: Iterable[FileTypes], max_concurrency: int = 5, file_ids: SequenceNotStr[str] = [], poll_interval_ms: int | Omit = omit, chunking_strategy: FileChunkingStrategyParam | Omit = omit, ) -> VectorStoreFileBatch: """Uploads the given files concurrently and then creates a vector store file batch. If you've already uploaded certain files that you want to include in this batch then you can pass their IDs through the `file_ids` argument. By default, if any file upload fails then an exception will be eagerly raised. The number of concurrency uploads is configurable using the `max_concurrency` parameter. Note: this method only supports `asyncio` or `trio` as the backing async runtime. """ results: list[FileObject] = [] with ThreadPoolExecutor(max_workers=max_concurrency) as executor: futures: list[Future[FileObject]] = [ executor.submit( self._client.files.create, file=file, purpose="assistants", ) for file in files ] for future in as_completed(futures): exc = future.exception() if exc: raise exc results.append(future.result()) batch = self.create_and_poll( vector_store_id=vector_store_id, file_ids=[*file_ids, *(f.id for f in results)], poll_interval_ms=poll_interval_ms, chunking_strategy=chunking_strategy, ) return batch class AsyncFileBatches(AsyncAPIResource): @cached_property def with_raw_response(self) -> AsyncFileBatchesWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncFileBatchesWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncFileBatchesWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncFileBatchesWithStreamingResponse(self) async def create( self, vector_store_id: str, *, attributes: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, chunking_strategy: FileChunkingStrategyParam | Omit = omit, file_ids: SequenceNotStr[str] | Omit = omit, files: Iterable[file_batch_create_params.File] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreFileBatch: """ Create a vector store file batch. Args: attributes: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters, booleans, or numbers. chunking_strategy: The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. Only applicable if `file_ids` is non-empty. file_ids: A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the vector store should use. Useful for tools like `file_search` that can access files. If `attributes` or `chunking_strategy` are provided, they will be applied to all files in the batch. The maximum batch size is 2000 files. Mutually exclusive with `files`. files: A list of objects that each include a `file_id` plus optional `attributes` or `chunking_strategy`. Use this when you need to override metadata for specific files. The global `attributes` or `chunking_strategy` will be ignored and must be specified for each file. The maximum batch size is 2000 files. Mutually exclusive with `file_ids`. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._post( f"/vector_stores/{vector_store_id}/file_batches", body=await async_maybe_transform( { "attributes": attributes, "chunking_strategy": chunking_strategy, "file_ids": file_ids, "files": files, }, file_batch_create_params.FileBatchCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStoreFileBatch, ) async def retrieve( self, batch_id: str, *, vector_store_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreFileBatch: """ Retrieves a vector store file batch. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") if not batch_id: raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._get( f"/vector_stores/{vector_store_id}/file_batches/{batch_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStoreFileBatch, ) async def cancel( self, batch_id: str, *, vector_store_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreFileBatch: """Cancel a vector store file batch. This attempts to cancel the processing of files in this batch as soon as possible. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") if not batch_id: raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._post( f"/vector_stores/{vector_store_id}/file_batches/{batch_id}/cancel", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStoreFileBatch, ) async def create_and_poll( self, vector_store_id: str, *, attributes: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, chunking_strategy: FileChunkingStrategyParam | Omit = omit, file_ids: SequenceNotStr[str] | Omit = omit, files: Iterable[file_batch_create_params.File] | Omit = omit, poll_interval_ms: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreFileBatch: """Create a vector store batch and poll until all files have been processed.""" batch = await self.create( vector_store_id=vector_store_id, attributes=attributes, chunking_strategy=chunking_strategy, file_ids=file_ids, files=files, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, ) # TODO: don't poll unless necessary?? return await self.poll( batch.id, vector_store_id=vector_store_id, poll_interval_ms=poll_interval_ms, ) def list_files( self, batch_id: str, *, vector_store_id: str, after: str | Omit = omit, before: str | Omit = omit, filter: Literal["in_progress", "completed", "failed", "cancelled"] | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[VectorStoreFile, AsyncCursorPage[VectorStoreFile]]: """ Returns a list of vector store files in a batch. Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. before: A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. filter: Filter by file status. One of `in_progress`, `completed`, `failed`, `cancelled`. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") if not batch_id: raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get_api_list( f"/vector_stores/{vector_store_id}/file_batches/{batch_id}/files", page=AsyncCursorPage[VectorStoreFile], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "filter": filter, "limit": limit, "order": order, }, file_batch_list_files_params.FileBatchListFilesParams, ), ), model=VectorStoreFile, ) async def poll( self, batch_id: str, *, vector_store_id: str, poll_interval_ms: int | Omit = omit, ) -> VectorStoreFileBatch: """Wait for the given file batch to be processed. Note: this will return even if one of the files failed to process, you need to check batch.file_counts.failed_count to handle this case. """ headers: dict[str, str] = {"X-Stainless-Poll-Helper": "true"} if is_given(poll_interval_ms): headers["X-Stainless-Custom-Poll-Interval"] = str(poll_interval_ms) while True: response = await self.with_raw_response.retrieve( batch_id, vector_store_id=vector_store_id, extra_headers=headers, ) batch = response.parse() if batch.file_counts.in_progress > 0: if not is_given(poll_interval_ms): from_header = response.headers.get("openai-poll-after-ms") if from_header is not None: poll_interval_ms = int(from_header) else: poll_interval_ms = 1000 await self._sleep(poll_interval_ms / 1000) continue return batch async def upload_and_poll( self, vector_store_id: str, *, files: Iterable[FileTypes], max_concurrency: int = 5, file_ids: SequenceNotStr[str] = [], poll_interval_ms: int | Omit = omit, chunking_strategy: FileChunkingStrategyParam | Omit = omit, ) -> VectorStoreFileBatch: """Uploads the given files concurrently and then creates a vector store file batch. If you've already uploaded certain files that you want to include in this batch then you can pass their IDs through the `file_ids` argument. By default, if any file upload fails then an exception will be eagerly raised. The number of concurrency uploads is configurable using the `max_concurrency` parameter. Note: this method only supports `asyncio` or `trio` as the backing async runtime. """ uploaded_files: list[FileObject] = [] async_library = sniffio.current_async_library() if async_library == "asyncio": async def asyncio_upload_file(semaphore: asyncio.Semaphore, file: FileTypes) -> None: async with semaphore: file_obj = await self._client.files.create( file=file, purpose="assistants", ) uploaded_files.append(file_obj) semaphore = asyncio.Semaphore(max_concurrency) tasks = [asyncio_upload_file(semaphore, file) for file in files] await asyncio.gather(*tasks) elif async_library == "trio": # We only import if the library is being used. # We support Python 3.7 so are using an older version of trio that does not have type information import trio # type: ignore # pyright: ignore[reportMissingTypeStubs] async def trio_upload_file(limiter: trio.CapacityLimiter, file: FileTypes) -> None: async with limiter: file_obj = await self._client.files.create( file=file, purpose="assistants", ) uploaded_files.append(file_obj) limiter = trio.CapacityLimiter(max_concurrency) async with trio.open_nursery() as nursery: for file in files: nursery.start_soon(trio_upload_file, limiter, file) # pyright: ignore [reportUnknownMemberType] else: raise RuntimeError( f"Async runtime {async_library} is not supported yet. Only asyncio or trio is supported", ) batch = await self.create_and_poll( vector_store_id=vector_store_id, file_ids=[*file_ids, *(f.id for f in uploaded_files)], poll_interval_ms=poll_interval_ms, chunking_strategy=chunking_strategy, ) return batch class FileBatchesWithRawResponse: def __init__(self, file_batches: FileBatches) -> None: self._file_batches = file_batches self.create = _legacy_response.to_raw_response_wrapper( file_batches.create, ) self.retrieve = _legacy_response.to_raw_response_wrapper( file_batches.retrieve, ) self.cancel = _legacy_response.to_raw_response_wrapper( file_batches.cancel, ) self.list_files = _legacy_response.to_raw_response_wrapper( file_batches.list_files, ) class AsyncFileBatchesWithRawResponse: def __init__(self, file_batches: AsyncFileBatches) -> None: self._file_batches = file_batches self.create = _legacy_response.async_to_raw_response_wrapper( file_batches.create, ) self.retrieve = _legacy_response.async_to_raw_response_wrapper( file_batches.retrieve, ) self.cancel = _legacy_response.async_to_raw_response_wrapper( file_batches.cancel, ) self.list_files = _legacy_response.async_to_raw_response_wrapper( file_batches.list_files, ) class FileBatchesWithStreamingResponse: def __init__(self, file_batches: FileBatches) -> None: self._file_batches = file_batches self.create = to_streamed_response_wrapper( file_batches.create, ) self.retrieve = to_streamed_response_wrapper( file_batches.retrieve, ) self.cancel = to_streamed_response_wrapper( file_batches.cancel, ) self.list_files = to_streamed_response_wrapper( file_batches.list_files, ) class AsyncFileBatchesWithStreamingResponse: def __init__(self, file_batches: AsyncFileBatches) -> None: self._file_batches = file_batches self.create = async_to_streamed_response_wrapper( file_batches.create, ) self.retrieve = async_to_streamed_response_wrapper( file_batches.retrieve, ) self.cancel = async_to_streamed_response_wrapper( file_batches.cancel, ) self.list_files = async_to_streamed_response_wrapper( file_batches.list_files, ) ================================================ FILE: src/openai/resources/vector_stores/files.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import TYPE_CHECKING, Dict, Union, Optional from typing_extensions import Literal, assert_never import httpx from ... import _legacy_response from ...types import FileChunkingStrategyParam from ..._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given from ..._utils import is_given, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ...pagination import SyncPage, AsyncPage, SyncCursorPage, AsyncCursorPage from ..._base_client import AsyncPaginator, make_request_options from ...types.vector_stores import file_list_params, file_create_params, file_update_params from ...types.file_chunking_strategy_param import FileChunkingStrategyParam from ...types.vector_stores.vector_store_file import VectorStoreFile from ...types.vector_stores.file_content_response import FileContentResponse from ...types.vector_stores.vector_store_file_deleted import VectorStoreFileDeleted __all__ = ["Files", "AsyncFiles"] class Files(SyncAPIResource): @cached_property def with_raw_response(self) -> FilesWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return FilesWithRawResponse(self) @cached_property def with_streaming_response(self) -> FilesWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return FilesWithStreamingResponse(self) def create( self, vector_store_id: str, *, file_id: str, attributes: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, chunking_strategy: FileChunkingStrategyParam | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreFile: """ Create a vector store file by attaching a [File](https://platform.openai.com/docs/api-reference/files) to a [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object). Args: file_id: A [File](https://platform.openai.com/docs/api-reference/files) ID that the vector store should use. Useful for tools like `file_search` that can access files. attributes: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters, booleans, or numbers. chunking_strategy: The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. Only applicable if `file_ids` is non-empty. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._post( f"/vector_stores/{vector_store_id}/files", body=maybe_transform( { "file_id": file_id, "attributes": attributes, "chunking_strategy": chunking_strategy, }, file_create_params.FileCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStoreFile, ) def retrieve( self, file_id: str, *, vector_store_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreFile: """ Retrieves a vector store file. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get( f"/vector_stores/{vector_store_id}/files/{file_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStoreFile, ) def update( self, file_id: str, *, vector_store_id: str, attributes: Optional[Dict[str, Union[str, float, bool]]], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreFile: """ Update attributes on a vector store file. Args: attributes: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters, booleans, or numbers. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._post( f"/vector_stores/{vector_store_id}/files/{file_id}", body=maybe_transform({"attributes": attributes}, file_update_params.FileUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStoreFile, ) def list( self, vector_store_id: str, *, after: str | Omit = omit, before: str | Omit = omit, filter: Literal["in_progress", "completed", "failed", "cancelled"] | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[VectorStoreFile]: """ Returns a list of vector store files. Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. before: A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. filter: Filter by file status. One of `in_progress`, `completed`, `failed`, `cancelled`. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get_api_list( f"/vector_stores/{vector_store_id}/files", page=SyncCursorPage[VectorStoreFile], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "filter": filter, "limit": limit, "order": order, }, file_list_params.FileListParams, ), ), model=VectorStoreFile, ) def delete( self, file_id: str, *, vector_store_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreFileDeleted: """Delete a vector store file. This will remove the file from the vector store but the file itself will not be deleted. To delete the file, use the [delete file](https://platform.openai.com/docs/api-reference/files/delete) endpoint. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._delete( f"/vector_stores/{vector_store_id}/files/{file_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStoreFileDeleted, ) def create_and_poll( self, file_id: str, *, vector_store_id: str, attributes: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, poll_interval_ms: int | Omit = omit, chunking_strategy: FileChunkingStrategyParam | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreFile: """Attach a file to the given vector store and wait for it to be processed.""" self.create( vector_store_id=vector_store_id, file_id=file_id, chunking_strategy=chunking_strategy, attributes=attributes, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, ) return self.poll( file_id, vector_store_id=vector_store_id, poll_interval_ms=poll_interval_ms, ) def poll( self, file_id: str, *, vector_store_id: str, poll_interval_ms: int | Omit = omit, ) -> VectorStoreFile: """Wait for the vector store file to finish processing. Note: this will return even if the file failed to process, you need to check file.last_error and file.status to handle these cases """ headers: dict[str, str] = {"X-Stainless-Poll-Helper": "true"} if is_given(poll_interval_ms): headers["X-Stainless-Custom-Poll-Interval"] = str(poll_interval_ms) while True: response = self.with_raw_response.retrieve( file_id, vector_store_id=vector_store_id, extra_headers=headers, ) file = response.parse() if file.status == "in_progress": if not is_given(poll_interval_ms): from_header = response.headers.get("openai-poll-after-ms") if from_header is not None: poll_interval_ms = int(from_header) else: poll_interval_ms = 1000 self._sleep(poll_interval_ms / 1000) elif file.status == "cancelled" or file.status == "completed" or file.status == "failed": return file else: if TYPE_CHECKING: # type: ignore[unreachable] assert_never(file.status) else: return file def upload( self, *, vector_store_id: str, file: FileTypes, chunking_strategy: FileChunkingStrategyParam | Omit = omit, ) -> VectorStoreFile: """Upload a file to the `files` API and then attach it to the given vector store. Note the file will be asynchronously processed (you can use the alternative polling helper method to wait for processing to complete). """ file_obj = self._client.files.create(file=file, purpose="assistants") return self.create(vector_store_id=vector_store_id, file_id=file_obj.id, chunking_strategy=chunking_strategy) def upload_and_poll( self, *, vector_store_id: str, file: FileTypes, attributes: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, poll_interval_ms: int | Omit = omit, chunking_strategy: FileChunkingStrategyParam | Omit = omit, ) -> VectorStoreFile: """Add a file to a vector store and poll until processing is complete.""" file_obj = self._client.files.create(file=file, purpose="assistants") return self.create_and_poll( vector_store_id=vector_store_id, file_id=file_obj.id, chunking_strategy=chunking_strategy, poll_interval_ms=poll_interval_ms, attributes=attributes, ) def content( self, file_id: str, *, vector_store_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[FileContentResponse]: """ Retrieve the parsed contents of a vector store file. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get_api_list( f"/vector_stores/{vector_store_id}/files/{file_id}/content", page=SyncPage[FileContentResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), model=FileContentResponse, ) class AsyncFiles(AsyncAPIResource): @cached_property def with_raw_response(self) -> AsyncFilesWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncFilesWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncFilesWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncFilesWithStreamingResponse(self) async def create( self, vector_store_id: str, *, file_id: str, attributes: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, chunking_strategy: FileChunkingStrategyParam | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreFile: """ Create a vector store file by attaching a [File](https://platform.openai.com/docs/api-reference/files) to a [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object). Args: file_id: A [File](https://platform.openai.com/docs/api-reference/files) ID that the vector store should use. Useful for tools like `file_search` that can access files. attributes: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters, booleans, or numbers. chunking_strategy: The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. Only applicable if `file_ids` is non-empty. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._post( f"/vector_stores/{vector_store_id}/files", body=await async_maybe_transform( { "file_id": file_id, "attributes": attributes, "chunking_strategy": chunking_strategy, }, file_create_params.FileCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStoreFile, ) async def retrieve( self, file_id: str, *, vector_store_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreFile: """ Retrieves a vector store file. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._get( f"/vector_stores/{vector_store_id}/files/{file_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStoreFile, ) async def update( self, file_id: str, *, vector_store_id: str, attributes: Optional[Dict[str, Union[str, float, bool]]], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreFile: """ Update attributes on a vector store file. Args: attributes: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters, booleans, or numbers. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._post( f"/vector_stores/{vector_store_id}/files/{file_id}", body=await async_maybe_transform({"attributes": attributes}, file_update_params.FileUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStoreFile, ) def list( self, vector_store_id: str, *, after: str | Omit = omit, before: str | Omit = omit, filter: Literal["in_progress", "completed", "failed", "cancelled"] | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[VectorStoreFile, AsyncCursorPage[VectorStoreFile]]: """ Returns a list of vector store files. Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. before: A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. filter: Filter by file status. One of `in_progress`, `completed`, `failed`, `cancelled`. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get_api_list( f"/vector_stores/{vector_store_id}/files", page=AsyncCursorPage[VectorStoreFile], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "filter": filter, "limit": limit, "order": order, }, file_list_params.FileListParams, ), ), model=VectorStoreFile, ) async def delete( self, file_id: str, *, vector_store_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreFileDeleted: """Delete a vector store file. This will remove the file from the vector store but the file itself will not be deleted. To delete the file, use the [delete file](https://platform.openai.com/docs/api-reference/files/delete) endpoint. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._delete( f"/vector_stores/{vector_store_id}/files/{file_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStoreFileDeleted, ) async def create_and_poll( self, file_id: str, *, vector_store_id: str, attributes: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, poll_interval_ms: int | Omit = omit, chunking_strategy: FileChunkingStrategyParam | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreFile: """Attach a file to the given vector store and wait for it to be processed.""" await self.create( vector_store_id=vector_store_id, file_id=file_id, chunking_strategy=chunking_strategy, attributes=attributes, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, ) return await self.poll( file_id, vector_store_id=vector_store_id, poll_interval_ms=poll_interval_ms, ) async def poll( self, file_id: str, *, vector_store_id: str, poll_interval_ms: int | Omit = omit, ) -> VectorStoreFile: """Wait for the vector store file to finish processing. Note: this will return even if the file failed to process, you need to check file.last_error and file.status to handle these cases """ headers: dict[str, str] = {"X-Stainless-Poll-Helper": "true"} if is_given(poll_interval_ms): headers["X-Stainless-Custom-Poll-Interval"] = str(poll_interval_ms) while True: response = await self.with_raw_response.retrieve( file_id, vector_store_id=vector_store_id, extra_headers=headers, ) file = response.parse() if file.status == "in_progress": if not is_given(poll_interval_ms): from_header = response.headers.get("openai-poll-after-ms") if from_header is not None: poll_interval_ms = int(from_header) else: poll_interval_ms = 1000 await self._sleep(poll_interval_ms / 1000) elif file.status == "cancelled" or file.status == "completed" or file.status == "failed": return file else: if TYPE_CHECKING: # type: ignore[unreachable] assert_never(file.status) else: return file async def upload( self, *, vector_store_id: str, file: FileTypes, chunking_strategy: FileChunkingStrategyParam | Omit = omit, ) -> VectorStoreFile: """Upload a file to the `files` API and then attach it to the given vector store. Note the file will be asynchronously processed (you can use the alternative polling helper method to wait for processing to complete). """ file_obj = await self._client.files.create(file=file, purpose="assistants") return await self.create( vector_store_id=vector_store_id, file_id=file_obj.id, chunking_strategy=chunking_strategy ) async def upload_and_poll( self, *, vector_store_id: str, file: FileTypes, attributes: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, poll_interval_ms: int | Omit = omit, chunking_strategy: FileChunkingStrategyParam | Omit = omit, ) -> VectorStoreFile: """Add a file to a vector store and poll until processing is complete.""" file_obj = await self._client.files.create(file=file, purpose="assistants") return await self.create_and_poll( vector_store_id=vector_store_id, file_id=file_obj.id, poll_interval_ms=poll_interval_ms, chunking_strategy=chunking_strategy, attributes=attributes, ) def content( self, file_id: str, *, vector_store_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[FileContentResponse, AsyncPage[FileContentResponse]]: """ Retrieve the parsed contents of a vector store file. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get_api_list( f"/vector_stores/{vector_store_id}/files/{file_id}/content", page=AsyncPage[FileContentResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), model=FileContentResponse, ) class FilesWithRawResponse: def __init__(self, files: Files) -> None: self._files = files self.create = _legacy_response.to_raw_response_wrapper( files.create, ) self.retrieve = _legacy_response.to_raw_response_wrapper( files.retrieve, ) self.update = _legacy_response.to_raw_response_wrapper( files.update, ) self.list = _legacy_response.to_raw_response_wrapper( files.list, ) self.delete = _legacy_response.to_raw_response_wrapper( files.delete, ) self.content = _legacy_response.to_raw_response_wrapper( files.content, ) class AsyncFilesWithRawResponse: def __init__(self, files: AsyncFiles) -> None: self._files = files self.create = _legacy_response.async_to_raw_response_wrapper( files.create, ) self.retrieve = _legacy_response.async_to_raw_response_wrapper( files.retrieve, ) self.update = _legacy_response.async_to_raw_response_wrapper( files.update, ) self.list = _legacy_response.async_to_raw_response_wrapper( files.list, ) self.delete = _legacy_response.async_to_raw_response_wrapper( files.delete, ) self.content = _legacy_response.async_to_raw_response_wrapper( files.content, ) class FilesWithStreamingResponse: def __init__(self, files: Files) -> None: self._files = files self.create = to_streamed_response_wrapper( files.create, ) self.retrieve = to_streamed_response_wrapper( files.retrieve, ) self.update = to_streamed_response_wrapper( files.update, ) self.list = to_streamed_response_wrapper( files.list, ) self.delete = to_streamed_response_wrapper( files.delete, ) self.content = to_streamed_response_wrapper( files.content, ) class AsyncFilesWithStreamingResponse: def __init__(self, files: AsyncFiles) -> None: self._files = files self.create = async_to_streamed_response_wrapper( files.create, ) self.retrieve = async_to_streamed_response_wrapper( files.retrieve, ) self.update = async_to_streamed_response_wrapper( files.update, ) self.list = async_to_streamed_response_wrapper( files.list, ) self.delete = async_to_streamed_response_wrapper( files.delete, ) self.content = async_to_streamed_response_wrapper( files.content, ) ================================================ FILE: src/openai/resources/vector_stores/vector_stores.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Optional from typing_extensions import Literal import httpx from ... import _legacy_response from .files import ( Files, AsyncFiles, FilesWithRawResponse, AsyncFilesWithRawResponse, FilesWithStreamingResponse, AsyncFilesWithStreamingResponse, ) from ...types import ( FileChunkingStrategyParam, vector_store_list_params, vector_store_create_params, vector_store_search_params, vector_store_update_params, ) from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from ...pagination import SyncPage, AsyncPage, SyncCursorPage, AsyncCursorPage from .file_batches import ( FileBatches, AsyncFileBatches, FileBatchesWithRawResponse, AsyncFileBatchesWithRawResponse, FileBatchesWithStreamingResponse, AsyncFileBatchesWithStreamingResponse, ) from ..._base_client import AsyncPaginator, make_request_options from ...types.vector_store import VectorStore from ...types.vector_store_deleted import VectorStoreDeleted from ...types.shared_params.metadata import Metadata from ...types.file_chunking_strategy_param import FileChunkingStrategyParam from ...types.vector_store_search_response import VectorStoreSearchResponse __all__ = ["VectorStores", "AsyncVectorStores"] class VectorStores(SyncAPIResource): @cached_property def files(self) -> Files: return Files(self._client) @cached_property def file_batches(self) -> FileBatches: return FileBatches(self._client) @cached_property def with_raw_response(self) -> VectorStoresWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return VectorStoresWithRawResponse(self) @cached_property def with_streaming_response(self) -> VectorStoresWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return VectorStoresWithStreamingResponse(self) def create( self, *, chunking_strategy: FileChunkingStrategyParam | Omit = omit, description: str | Omit = omit, expires_after: vector_store_create_params.ExpiresAfter | Omit = omit, file_ids: SequenceNotStr[str] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, name: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStore: """ Create a vector store. Args: chunking_strategy: The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. Only applicable if `file_ids` is non-empty. description: A description for the vector store. Can be used to describe the vector store's purpose. expires_after: The expiration policy for a vector store. file_ids: A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the vector store should use. Useful for tools like `file_search` that can access files. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. name: The name of the vector store. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._post( "/vector_stores", body=maybe_transform( { "chunking_strategy": chunking_strategy, "description": description, "expires_after": expires_after, "file_ids": file_ids, "metadata": metadata, "name": name, }, vector_store_create_params.VectorStoreCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStore, ) def retrieve( self, vector_store_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStore: """ Retrieves a vector store. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get( f"/vector_stores/{vector_store_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStore, ) def update( self, vector_store_id: str, *, expires_after: Optional[vector_store_update_params.ExpiresAfter] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, name: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStore: """ Modifies a vector store. Args: expires_after: The expiration policy for a vector store. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. name: The name of the vector store. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._post( f"/vector_stores/{vector_store_id}", body=maybe_transform( { "expires_after": expires_after, "metadata": metadata, "name": name, }, vector_store_update_params.VectorStoreUpdateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStore, ) def list( self, *, after: str | Omit = omit, before: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[VectorStore]: """Returns a list of vector stores. Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. before: A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get_api_list( "/vector_stores", page=SyncCursorPage[VectorStore], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "limit": limit, "order": order, }, vector_store_list_params.VectorStoreListParams, ), ), model=VectorStore, ) def delete( self, vector_store_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreDeleted: """ Delete a vector store. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._delete( f"/vector_stores/{vector_store_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStoreDeleted, ) def search( self, vector_store_id: str, *, query: Union[str, SequenceNotStr[str]], filters: vector_store_search_params.Filters | Omit = omit, max_num_results: int | Omit = omit, ranking_options: vector_store_search_params.RankingOptions | Omit = omit, rewrite_query: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[VectorStoreSearchResponse]: """ Search a vector store for relevant chunks based on a query and file attributes filter. Args: query: A query string for a search filters: A filter to apply based on file attributes. max_num_results: The maximum number of results to return. This number should be between 1 and 50 inclusive. ranking_options: Ranking options for search. rewrite_query: Whether to rewrite the natural language query for vector search. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get_api_list( f"/vector_stores/{vector_store_id}/search", page=SyncPage[VectorStoreSearchResponse], body=maybe_transform( { "query": query, "filters": filters, "max_num_results": max_num_results, "ranking_options": ranking_options, "rewrite_query": rewrite_query, }, vector_store_search_params.VectorStoreSearchParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), model=VectorStoreSearchResponse, method="post", ) class AsyncVectorStores(AsyncAPIResource): @cached_property def files(self) -> AsyncFiles: return AsyncFiles(self._client) @cached_property def file_batches(self) -> AsyncFileBatches: return AsyncFileBatches(self._client) @cached_property def with_raw_response(self) -> AsyncVectorStoresWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncVectorStoresWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncVectorStoresWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncVectorStoresWithStreamingResponse(self) async def create( self, *, chunking_strategy: FileChunkingStrategyParam | Omit = omit, description: str | Omit = omit, expires_after: vector_store_create_params.ExpiresAfter | Omit = omit, file_ids: SequenceNotStr[str] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, name: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStore: """ Create a vector store. Args: chunking_strategy: The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. Only applicable if `file_ids` is non-empty. description: A description for the vector store. Can be used to describe the vector store's purpose. expires_after: The expiration policy for a vector store. file_ids: A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the vector store should use. Useful for tools like `file_search` that can access files. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. name: The name of the vector store. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._post( "/vector_stores", body=await async_maybe_transform( { "chunking_strategy": chunking_strategy, "description": description, "expires_after": expires_after, "file_ids": file_ids, "metadata": metadata, "name": name, }, vector_store_create_params.VectorStoreCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStore, ) async def retrieve( self, vector_store_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStore: """ Retrieves a vector store. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._get( f"/vector_stores/{vector_store_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStore, ) async def update( self, vector_store_id: str, *, expires_after: Optional[vector_store_update_params.ExpiresAfter] | Omit = omit, metadata: Optional[Metadata] | Omit = omit, name: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStore: """ Modifies a vector store. Args: expires_after: The expiration policy for a vector store. metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. name: The name of the vector store. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._post( f"/vector_stores/{vector_store_id}", body=await async_maybe_transform( { "expires_after": expires_after, "metadata": metadata, "name": name, }, vector_store_update_params.VectorStoreUpdateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStore, ) def list( self, *, after: str | Omit = omit, before: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[VectorStore, AsyncCursorPage[VectorStore]]: """Returns a list of vector stores. Args: after: A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. before: A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get_api_list( "/vector_stores", page=AsyncCursorPage[VectorStore], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "limit": limit, "order": order, }, vector_store_list_params.VectorStoreListParams, ), ), model=VectorStore, ) async def delete( self, vector_store_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VectorStoreDeleted: """ Delete a vector store. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return await self._delete( f"/vector_stores/{vector_store_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VectorStoreDeleted, ) def search( self, vector_store_id: str, *, query: Union[str, SequenceNotStr[str]], filters: vector_store_search_params.Filters | Omit = omit, max_num_results: int | Omit = omit, ranking_options: vector_store_search_params.RankingOptions | Omit = omit, rewrite_query: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[VectorStoreSearchResponse, AsyncPage[VectorStoreSearchResponse]]: """ Search a vector store for relevant chunks based on a query and file attributes filter. Args: query: A query string for a search filters: A filter to apply based on file attributes. max_num_results: The maximum number of results to return. This number should be between 1 and 50 inclusive. ranking_options: Ranking options for search. rewrite_query: Whether to rewrite the natural language query for vector search. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not vector_store_id: raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})} return self._get_api_list( f"/vector_stores/{vector_store_id}/search", page=AsyncPage[VectorStoreSearchResponse], body=maybe_transform( { "query": query, "filters": filters, "max_num_results": max_num_results, "ranking_options": ranking_options, "rewrite_query": rewrite_query, }, vector_store_search_params.VectorStoreSearchParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), model=VectorStoreSearchResponse, method="post", ) class VectorStoresWithRawResponse: def __init__(self, vector_stores: VectorStores) -> None: self._vector_stores = vector_stores self.create = _legacy_response.to_raw_response_wrapper( vector_stores.create, ) self.retrieve = _legacy_response.to_raw_response_wrapper( vector_stores.retrieve, ) self.update = _legacy_response.to_raw_response_wrapper( vector_stores.update, ) self.list = _legacy_response.to_raw_response_wrapper( vector_stores.list, ) self.delete = _legacy_response.to_raw_response_wrapper( vector_stores.delete, ) self.search = _legacy_response.to_raw_response_wrapper( vector_stores.search, ) @cached_property def files(self) -> FilesWithRawResponse: return FilesWithRawResponse(self._vector_stores.files) @cached_property def file_batches(self) -> FileBatchesWithRawResponse: return FileBatchesWithRawResponse(self._vector_stores.file_batches) class AsyncVectorStoresWithRawResponse: def __init__(self, vector_stores: AsyncVectorStores) -> None: self._vector_stores = vector_stores self.create = _legacy_response.async_to_raw_response_wrapper( vector_stores.create, ) self.retrieve = _legacy_response.async_to_raw_response_wrapper( vector_stores.retrieve, ) self.update = _legacy_response.async_to_raw_response_wrapper( vector_stores.update, ) self.list = _legacy_response.async_to_raw_response_wrapper( vector_stores.list, ) self.delete = _legacy_response.async_to_raw_response_wrapper( vector_stores.delete, ) self.search = _legacy_response.async_to_raw_response_wrapper( vector_stores.search, ) @cached_property def files(self) -> AsyncFilesWithRawResponse: return AsyncFilesWithRawResponse(self._vector_stores.files) @cached_property def file_batches(self) -> AsyncFileBatchesWithRawResponse: return AsyncFileBatchesWithRawResponse(self._vector_stores.file_batches) class VectorStoresWithStreamingResponse: def __init__(self, vector_stores: VectorStores) -> None: self._vector_stores = vector_stores self.create = to_streamed_response_wrapper( vector_stores.create, ) self.retrieve = to_streamed_response_wrapper( vector_stores.retrieve, ) self.update = to_streamed_response_wrapper( vector_stores.update, ) self.list = to_streamed_response_wrapper( vector_stores.list, ) self.delete = to_streamed_response_wrapper( vector_stores.delete, ) self.search = to_streamed_response_wrapper( vector_stores.search, ) @cached_property def files(self) -> FilesWithStreamingResponse: return FilesWithStreamingResponse(self._vector_stores.files) @cached_property def file_batches(self) -> FileBatchesWithStreamingResponse: return FileBatchesWithStreamingResponse(self._vector_stores.file_batches) class AsyncVectorStoresWithStreamingResponse: def __init__(self, vector_stores: AsyncVectorStores) -> None: self._vector_stores = vector_stores self.create = async_to_streamed_response_wrapper( vector_stores.create, ) self.retrieve = async_to_streamed_response_wrapper( vector_stores.retrieve, ) self.update = async_to_streamed_response_wrapper( vector_stores.update, ) self.list = async_to_streamed_response_wrapper( vector_stores.list, ) self.delete = async_to_streamed_response_wrapper( vector_stores.delete, ) self.search = async_to_streamed_response_wrapper( vector_stores.search, ) @cached_property def files(self) -> AsyncFilesWithStreamingResponse: return AsyncFilesWithStreamingResponse(self._vector_stores.files) @cached_property def file_batches(self) -> AsyncFileBatchesWithStreamingResponse: return AsyncFileBatchesWithStreamingResponse(self._vector_stores.file_batches) ================================================ FILE: src/openai/resources/videos.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import TYPE_CHECKING, Mapping, cast from typing_extensions import Literal, assert_never import httpx from .. import _legacy_response from ..types import ( VideoSize, VideoSeconds, video_edit_params, video_list_params, video_remix_params, video_create_params, video_extend_params, video_create_character_params, video_download_content_params, ) from .._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( StreamedBinaryAPIResponse, AsyncStreamedBinaryAPIResponse, to_streamed_response_wrapper, async_to_streamed_response_wrapper, to_custom_streamed_response_wrapper, async_to_custom_streamed_response_wrapper, ) from ..pagination import SyncConversationCursorPage, AsyncConversationCursorPage from ..types.video import Video from .._base_client import AsyncPaginator, make_request_options from .._utils._utils import is_given from ..types.video_size import VideoSize from ..types.video_seconds import VideoSeconds from ..types.video_model_param import VideoModelParam from ..types.video_delete_response import VideoDeleteResponse from ..types.video_get_character_response import VideoGetCharacterResponse from ..types.video_create_character_response import VideoCreateCharacterResponse __all__ = ["Videos", "AsyncVideos"] class Videos(SyncAPIResource): @cached_property def with_raw_response(self) -> VideosWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return VideosWithRawResponse(self) @cached_property def with_streaming_response(self) -> VideosWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return VideosWithStreamingResponse(self) def create( self, *, prompt: str, input_reference: video_create_params.InputReference | Omit = omit, model: VideoModelParam | Omit = omit, seconds: VideoSeconds | Omit = omit, size: VideoSize | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Video: """ Create a new video generation job from a prompt and optional reference assets. Args: prompt: Text prompt that describes the video to generate. input_reference: Optional reference asset upload or reference object that guides generation. model: The video generation model to use (allowed values: sora-2, sora-2-pro). Defaults to `sora-2`. seconds: Clip duration in seconds (allowed values: 4, 8, 12). Defaults to 4 seconds. size: Output resolution formatted as width x height (allowed values: 720x1280, 1280x720, 1024x1792, 1792x1024). Defaults to 720x1280. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ body = deepcopy_minimal( { "prompt": prompt, "input_reference": input_reference, "model": model, "seconds": seconds, "size": size, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["input_reference"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return self._post( "/videos", body=maybe_transform(body, video_create_params.VideoCreateParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Video, ) def create_and_poll( self, *, prompt: str, input_reference: video_create_params.InputReference | Omit = omit, model: VideoModelParam | Omit = omit, seconds: VideoSeconds | Omit = omit, size: VideoSize | Omit = omit, poll_interval_ms: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Video: """Create a video and wait for it to be processed.""" video = self.create( model=model, prompt=prompt, input_reference=input_reference, seconds=seconds, size=size, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, ) return self.poll( video.id, poll_interval_ms=poll_interval_ms, ) def poll( self, video_id: str, *, poll_interval_ms: int | Omit = omit, ) -> Video: """Wait for the vector store file to finish processing. Note: this will return even if the file failed to process, you need to check file.last_error and file.status to handle these cases """ headers: dict[str, str] = {"X-Stainless-Poll-Helper": "true"} if is_given(poll_interval_ms): headers["X-Stainless-Custom-Poll-Interval"] = str(poll_interval_ms) while True: response = self.with_raw_response.retrieve( video_id, extra_headers=headers, ) video = response.parse() if video.status == "in_progress" or video.status == "queued": if not is_given(poll_interval_ms): from_header = response.headers.get("openai-poll-after-ms") if from_header is not None: poll_interval_ms = int(from_header) else: poll_interval_ms = 1000 self._sleep(poll_interval_ms / 1000) elif video.status == "completed" or video.status == "failed": return video else: if TYPE_CHECKING: # type: ignore[unreachable] assert_never(video.status) else: return video def retrieve( self, video_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Video: """ Fetch the latest metadata for a generated video. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not video_id: raise ValueError(f"Expected a non-empty value for `video_id` but received {video_id!r}") return self._get( f"/videos/{video_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Video, ) def list( self, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncConversationCursorPage[Video]: """ List recently generated videos for the current project. Args: after: Identifier for the last item from the previous pagination request limit: Number of items to retrieve order: Sort order of results by timestamp. Use `asc` for ascending order or `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._get_api_list( "/videos", page=SyncConversationCursorPage[Video], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, }, video_list_params.VideoListParams, ), ), model=Video, ) def delete( self, video_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VideoDeleteResponse: """ Permanently delete a completed or failed video and its stored assets. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not video_id: raise ValueError(f"Expected a non-empty value for `video_id` but received {video_id!r}") return self._delete( f"/videos/{video_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VideoDeleteResponse, ) def create_character( self, *, name: str, video: FileTypes, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VideoCreateCharacterResponse: """ Create a character from an uploaded video. Args: name: Display name for this API character. video: Video file used to create a character. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ body = deepcopy_minimal( { "name": name, "video": video, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["video"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return self._post( "/videos/characters", body=maybe_transform(body, video_create_character_params.VideoCreateCharacterParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VideoCreateCharacterResponse, ) def download_content( self, video_id: str, *, variant: Literal["video", "thumbnail", "spritesheet"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: """ Download the generated video bytes or a derived preview asset. Streams the rendered video content for the specified video job. Args: variant: Which downloadable asset to return. Defaults to the MP4 video. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not video_id: raise ValueError(f"Expected a non-empty value for `video_id` but received {video_id!r}") extra_headers = {"Accept": "application/binary", **(extra_headers or {})} return self._get( f"/videos/{video_id}/content", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform({"variant": variant}, video_download_content_params.VideoDownloadContentParams), ), cast_to=_legacy_response.HttpxBinaryResponseContent, ) def edit( self, *, prompt: str, video: video_edit_params.Video, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Video: """ Create a new video generation job by editing a source video or existing generated video. Args: prompt: Text prompt that describes how to edit the source video. video: Reference to the completed video to edit. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ body = deepcopy_minimal( { "prompt": prompt, "video": video, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["video"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return self._post( "/videos/edits", body=maybe_transform(body, video_edit_params.VideoEditParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Video, ) def extend( self, *, prompt: str, seconds: VideoSeconds, video: video_extend_params.Video, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Video: """ Create an extension of a completed video. Args: prompt: Updated text prompt that directs the extension generation. seconds: Length of the newly generated extension segment in seconds (allowed values: 4, 8, 12, 16, 20). video: Reference to the completed video to extend. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ body = deepcopy_minimal( { "prompt": prompt, "seconds": seconds, "video": video, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["video"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return self._post( "/videos/extensions", body=maybe_transform(body, video_extend_params.VideoExtendParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Video, ) def get_character( self, character_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VideoGetCharacterResponse: """ Fetch a character. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not character_id: raise ValueError(f"Expected a non-empty value for `character_id` but received {character_id!r}") return self._get( f"/videos/characters/{character_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VideoGetCharacterResponse, ) def remix( self, video_id: str, *, prompt: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Video: """ Create a remix of a completed video using a refreshed prompt. Args: prompt: Updated text prompt that directs the remix generation. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not video_id: raise ValueError(f"Expected a non-empty value for `video_id` but received {video_id!r}") return self._post( f"/videos/{video_id}/remix", body=maybe_transform({"prompt": prompt}, video_remix_params.VideoRemixParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Video, ) class AsyncVideos(AsyncAPIResource): @cached_property def with_raw_response(self) -> AsyncVideosWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers """ return AsyncVideosWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncVideosWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/openai/openai-python#with_streaming_response """ return AsyncVideosWithStreamingResponse(self) async def create( self, *, prompt: str, input_reference: video_create_params.InputReference | Omit = omit, model: VideoModelParam | Omit = omit, seconds: VideoSeconds | Omit = omit, size: VideoSize | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Video: """ Create a new video generation job from a prompt and optional reference assets. Args: prompt: Text prompt that describes the video to generate. input_reference: Optional reference asset upload or reference object that guides generation. model: The video generation model to use (allowed values: sora-2, sora-2-pro). Defaults to `sora-2`. seconds: Clip duration in seconds (allowed values: 4, 8, 12). Defaults to 4 seconds. size: Output resolution formatted as width x height (allowed values: 720x1280, 1280x720, 1024x1792, 1792x1024). Defaults to 720x1280. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ body = deepcopy_minimal( { "prompt": prompt, "input_reference": input_reference, "model": model, "seconds": seconds, "size": size, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["input_reference"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return await self._post( "/videos", body=await async_maybe_transform(body, video_create_params.VideoCreateParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Video, ) async def create_and_poll( self, *, prompt: str, input_reference: video_create_params.InputReference | Omit = omit, model: VideoModelParam | Omit = omit, seconds: VideoSeconds | Omit = omit, size: VideoSize | Omit = omit, poll_interval_ms: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Video: """Create a video and wait for it to be processed.""" video = await self.create( model=model, prompt=prompt, input_reference=input_reference, seconds=seconds, size=size, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, ) return await self.poll( video.id, poll_interval_ms=poll_interval_ms, ) async def poll( self, video_id: str, *, poll_interval_ms: int | Omit = omit, ) -> Video: """Wait for the vector store file to finish processing. Note: this will return even if the file failed to process, you need to check file.last_error and file.status to handle these cases """ headers: dict[str, str] = {"X-Stainless-Poll-Helper": "true"} if is_given(poll_interval_ms): headers["X-Stainless-Custom-Poll-Interval"] = str(poll_interval_ms) while True: response = await self.with_raw_response.retrieve( video_id, extra_headers=headers, ) video = response.parse() if video.status == "in_progress" or video.status == "queued": if not is_given(poll_interval_ms): from_header = response.headers.get("openai-poll-after-ms") if from_header is not None: poll_interval_ms = int(from_header) else: poll_interval_ms = 1000 await self._sleep(poll_interval_ms / 1000) elif video.status == "completed" or video.status == "failed": return video else: if TYPE_CHECKING: # type: ignore[unreachable] assert_never(video.status) else: return video async def retrieve( self, video_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Video: """ Fetch the latest metadata for a generated video. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not video_id: raise ValueError(f"Expected a non-empty value for `video_id` but received {video_id!r}") return await self._get( f"/videos/{video_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Video, ) def list( self, *, after: str | Omit = omit, limit: int | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[Video, AsyncConversationCursorPage[Video]]: """ List recently generated videos for the current project. Args: after: Identifier for the last item from the previous pagination request limit: Number of items to retrieve order: Sort order of results by timestamp. Use `asc` for ascending order or `desc` for descending order. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ return self._get_api_list( "/videos", page=AsyncConversationCursorPage[Video], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "limit": limit, "order": order, }, video_list_params.VideoListParams, ), ), model=Video, ) async def delete( self, video_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VideoDeleteResponse: """ Permanently delete a completed or failed video and its stored assets. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not video_id: raise ValueError(f"Expected a non-empty value for `video_id` but received {video_id!r}") return await self._delete( f"/videos/{video_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VideoDeleteResponse, ) async def create_character( self, *, name: str, video: FileTypes, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VideoCreateCharacterResponse: """ Create a character from an uploaded video. Args: name: Display name for this API character. video: Video file used to create a character. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ body = deepcopy_minimal( { "name": name, "video": video, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["video"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return await self._post( "/videos/characters", body=await async_maybe_transform(body, video_create_character_params.VideoCreateCharacterParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VideoCreateCharacterResponse, ) async def download_content( self, video_id: str, *, variant: Literal["video", "thumbnail", "spritesheet"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: """ Download the generated video bytes or a derived preview asset. Streams the rendered video content for the specified video job. Args: variant: Which downloadable asset to return. Defaults to the MP4 video. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not video_id: raise ValueError(f"Expected a non-empty value for `video_id` but received {video_id!r}") extra_headers = {"Accept": "application/binary", **(extra_headers or {})} return await self._get( f"/videos/{video_id}/content", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=await async_maybe_transform( {"variant": variant}, video_download_content_params.VideoDownloadContentParams ), ), cast_to=_legacy_response.HttpxBinaryResponseContent, ) async def edit( self, *, prompt: str, video: video_edit_params.Video, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Video: """ Create a new video generation job by editing a source video or existing generated video. Args: prompt: Text prompt that describes how to edit the source video. video: Reference to the completed video to edit. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ body = deepcopy_minimal( { "prompt": prompt, "video": video, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["video"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return await self._post( "/videos/edits", body=await async_maybe_transform(body, video_edit_params.VideoEditParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Video, ) async def extend( self, *, prompt: str, seconds: VideoSeconds, video: video_extend_params.Video, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Video: """ Create an extension of a completed video. Args: prompt: Updated text prompt that directs the extension generation. seconds: Length of the newly generated extension segment in seconds (allowed values: 4, 8, 12, 16, 20). video: Reference to the completed video to extend. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ body = deepcopy_minimal( { "prompt": prompt, "seconds": seconds, "video": video, } ) files = extract_files(cast(Mapping[str, object], body), paths=[["video"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return await self._post( "/videos/extensions", body=await async_maybe_transform(body, video_extend_params.VideoExtendParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Video, ) async def get_character( self, character_id: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VideoGetCharacterResponse: """ Fetch a character. Args: extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not character_id: raise ValueError(f"Expected a non-empty value for `character_id` but received {character_id!r}") return await self._get( f"/videos/characters/{character_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=VideoGetCharacterResponse, ) async def remix( self, video_id: str, *, prompt: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Video: """ Create a remix of a completed video using a refreshed prompt. Args: prompt: Updated text prompt that directs the remix generation. extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not video_id: raise ValueError(f"Expected a non-empty value for `video_id` but received {video_id!r}") return await self._post( f"/videos/{video_id}/remix", body=await async_maybe_transform({"prompt": prompt}, video_remix_params.VideoRemixParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Video, ) class VideosWithRawResponse: def __init__(self, videos: Videos) -> None: self._videos = videos self.create = _legacy_response.to_raw_response_wrapper( videos.create, ) self.retrieve = _legacy_response.to_raw_response_wrapper( videos.retrieve, ) self.list = _legacy_response.to_raw_response_wrapper( videos.list, ) self.delete = _legacy_response.to_raw_response_wrapper( videos.delete, ) self.create_character = _legacy_response.to_raw_response_wrapper( videos.create_character, ) self.download_content = _legacy_response.to_raw_response_wrapper( videos.download_content, ) self.edit = _legacy_response.to_raw_response_wrapper( videos.edit, ) self.extend = _legacy_response.to_raw_response_wrapper( videos.extend, ) self.get_character = _legacy_response.to_raw_response_wrapper( videos.get_character, ) self.remix = _legacy_response.to_raw_response_wrapper( videos.remix, ) class AsyncVideosWithRawResponse: def __init__(self, videos: AsyncVideos) -> None: self._videos = videos self.create = _legacy_response.async_to_raw_response_wrapper( videos.create, ) self.retrieve = _legacy_response.async_to_raw_response_wrapper( videos.retrieve, ) self.list = _legacy_response.async_to_raw_response_wrapper( videos.list, ) self.delete = _legacy_response.async_to_raw_response_wrapper( videos.delete, ) self.create_character = _legacy_response.async_to_raw_response_wrapper( videos.create_character, ) self.download_content = _legacy_response.async_to_raw_response_wrapper( videos.download_content, ) self.edit = _legacy_response.async_to_raw_response_wrapper( videos.edit, ) self.extend = _legacy_response.async_to_raw_response_wrapper( videos.extend, ) self.get_character = _legacy_response.async_to_raw_response_wrapper( videos.get_character, ) self.remix = _legacy_response.async_to_raw_response_wrapper( videos.remix, ) class VideosWithStreamingResponse: def __init__(self, videos: Videos) -> None: self._videos = videos self.create = to_streamed_response_wrapper( videos.create, ) self.retrieve = to_streamed_response_wrapper( videos.retrieve, ) self.list = to_streamed_response_wrapper( videos.list, ) self.delete = to_streamed_response_wrapper( videos.delete, ) self.create_character = to_streamed_response_wrapper( videos.create_character, ) self.download_content = to_custom_streamed_response_wrapper( videos.download_content, StreamedBinaryAPIResponse, ) self.edit = to_streamed_response_wrapper( videos.edit, ) self.extend = to_streamed_response_wrapper( videos.extend, ) self.get_character = to_streamed_response_wrapper( videos.get_character, ) self.remix = to_streamed_response_wrapper( videos.remix, ) class AsyncVideosWithStreamingResponse: def __init__(self, videos: AsyncVideos) -> None: self._videos = videos self.create = async_to_streamed_response_wrapper( videos.create, ) self.retrieve = async_to_streamed_response_wrapper( videos.retrieve, ) self.list = async_to_streamed_response_wrapper( videos.list, ) self.delete = async_to_streamed_response_wrapper( videos.delete, ) self.create_character = async_to_streamed_response_wrapper( videos.create_character, ) self.download_content = async_to_custom_streamed_response_wrapper( videos.download_content, AsyncStreamedBinaryAPIResponse, ) self.edit = async_to_streamed_response_wrapper( videos.edit, ) self.extend = async_to_streamed_response_wrapper( videos.extend, ) self.get_character = async_to_streamed_response_wrapper( videos.get_character, ) self.remix = async_to_streamed_response_wrapper( videos.remix, ) ================================================ FILE: src/openai/resources/webhooks/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .webhooks import Webhooks as _Webhooks, AsyncWebhooks as _AsyncWebhooks class Webhooks(_Webhooks): pass class AsyncWebhooks(_AsyncWebhooks): pass __all__ = ["Webhooks", "AsyncWebhooks"] ================================================ FILE: src/openai/resources/webhooks/api.md ================================================ # Webhooks Types: ```python from openai.types.webhooks import ( BatchCancelledWebhookEvent, BatchCompletedWebhookEvent, BatchExpiredWebhookEvent, BatchFailedWebhookEvent, EvalRunCanceledWebhookEvent, EvalRunFailedWebhookEvent, EvalRunSucceededWebhookEvent, FineTuningJobCancelledWebhookEvent, FineTuningJobFailedWebhookEvent, FineTuningJobSucceededWebhookEvent, RealtimeCallIncomingWebhookEvent, ResponseCancelledWebhookEvent, ResponseCompletedWebhookEvent, ResponseFailedWebhookEvent, ResponseIncompleteWebhookEvent, UnwrapWebhookEvent, ) ``` ================================================ FILE: src/openai/resources/webhooks/webhooks.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import hmac import json import time import base64 import hashlib from typing import cast from ..._types import HeadersLike from ..._utils import get_required_header from ..._models import construct_type from ..._resource import SyncAPIResource, AsyncAPIResource from ..._exceptions import InvalidWebhookSignatureError from ...types.webhooks.unwrap_webhook_event import UnwrapWebhookEvent __all__ = ["Webhooks", "AsyncWebhooks"] class Webhooks(SyncAPIResource): def unwrap( self, payload: str | bytes, headers: HeadersLike, *, secret: str | None = None, ) -> UnwrapWebhookEvent: """Validates that the given payload was sent by OpenAI and parses the payload.""" if secret is None: secret = self._client.webhook_secret self.verify_signature(payload=payload, headers=headers, secret=secret) return cast( UnwrapWebhookEvent, construct_type( type_=UnwrapWebhookEvent, value=json.loads(payload), ), ) def verify_signature( self, payload: str | bytes, headers: HeadersLike, *, secret: str | None = None, tolerance: int = 300, ) -> None: """Validates whether or not the webhook payload was sent by OpenAI. Args: payload: The webhook payload headers: The webhook headers secret: The webhook secret (optional, will use client secret if not provided) tolerance: Maximum age of the webhook in seconds (default: 300 = 5 minutes) """ if secret is None: secret = self._client.webhook_secret if secret is None: raise ValueError( "The webhook secret must either be set using the env var, OPENAI_WEBHOOK_SECRET, " "on the client class, OpenAI(webhook_secret='123'), or passed to this function" ) signature_header = get_required_header(headers, "webhook-signature") timestamp = get_required_header(headers, "webhook-timestamp") webhook_id = get_required_header(headers, "webhook-id") # Validate timestamp to prevent replay attacks try: timestamp_seconds = int(timestamp) except ValueError: raise InvalidWebhookSignatureError("Invalid webhook timestamp format") from None now = int(time.time()) if now - timestamp_seconds > tolerance: raise InvalidWebhookSignatureError("Webhook timestamp is too old") from None if timestamp_seconds > now + tolerance: raise InvalidWebhookSignatureError("Webhook timestamp is too new") from None # Extract signatures from v1, format # The signature header can have multiple values, separated by spaces. # Each value is in the format v1,. We should accept if any match. signatures: list[str] = [] for part in signature_header.split(): if part.startswith("v1,"): signatures.append(part[3:]) else: signatures.append(part) # Decode the secret if it starts with whsec_ if secret.startswith("whsec_"): decoded_secret = base64.b64decode(secret[6:]) else: decoded_secret = secret.encode() body = payload.decode("utf-8") if isinstance(payload, bytes) else payload # Prepare the signed payload (OpenAI uses webhookId.timestamp.payload format) signed_payload = f"{webhook_id}.{timestamp}.{body}" expected_signature = base64.b64encode( hmac.new(decoded_secret, signed_payload.encode(), hashlib.sha256).digest() ).decode() # Accept if any signature matches if not any(hmac.compare_digest(expected_signature, sig) for sig in signatures): raise InvalidWebhookSignatureError( "The given webhook signature does not match the expected signature" ) from None class AsyncWebhooks(AsyncAPIResource): def unwrap( self, payload: str | bytes, headers: HeadersLike, *, secret: str | None = None, ) -> UnwrapWebhookEvent: """Validates that the given payload was sent by OpenAI and parses the payload.""" if secret is None: secret = self._client.webhook_secret self.verify_signature(payload=payload, headers=headers, secret=secret) body = payload.decode("utf-8") if isinstance(payload, bytes) else payload return cast( UnwrapWebhookEvent, construct_type( type_=UnwrapWebhookEvent, value=json.loads(body), ), ) def verify_signature( self, payload: str | bytes, headers: HeadersLike, *, secret: str | None = None, tolerance: int = 300, ) -> None: """Validates whether or not the webhook payload was sent by OpenAI. Args: payload: The webhook payload headers: The webhook headers secret: The webhook secret (optional, will use client secret if not provided) tolerance: Maximum age of the webhook in seconds (default: 300 = 5 minutes) """ if secret is None: secret = self._client.webhook_secret if secret is None: raise ValueError( "The webhook secret must either be set using the env var, OPENAI_WEBHOOK_SECRET, " "on the client class, OpenAI(webhook_secret='123'), or passed to this function" ) from None signature_header = get_required_header(headers, "webhook-signature") timestamp = get_required_header(headers, "webhook-timestamp") webhook_id = get_required_header(headers, "webhook-id") # Validate timestamp to prevent replay attacks try: timestamp_seconds = int(timestamp) except ValueError: raise InvalidWebhookSignatureError("Invalid webhook timestamp format") from None now = int(time.time()) if now - timestamp_seconds > tolerance: raise InvalidWebhookSignatureError("Webhook timestamp is too old") from None if timestamp_seconds > now + tolerance: raise InvalidWebhookSignatureError("Webhook timestamp is too new") from None # Extract signatures from v1, format # The signature header can have multiple values, separated by spaces. # Each value is in the format v1,. We should accept if any match. signatures: list[str] = [] for part in signature_header.split(): if part.startswith("v1,"): signatures.append(part[3:]) else: signatures.append(part) # Decode the secret if it starts with whsec_ if secret.startswith("whsec_"): decoded_secret = base64.b64decode(secret[6:]) else: decoded_secret = secret.encode() body = payload.decode("utf-8") if isinstance(payload, bytes) else payload # Prepare the signed payload (OpenAI uses webhookId.timestamp.payload format) signed_payload = f"{webhook_id}.{timestamp}.{body}" expected_signature = base64.b64encode( hmac.new(decoded_secret, signed_payload.encode(), hashlib.sha256).digest() ).decode() # Accept if any signature matches if not any(hmac.compare_digest(expected_signature, sig) for sig in signatures): raise InvalidWebhookSignatureError("The given webhook signature does not match the expected signature") ================================================ FILE: src/openai/types/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .batch import Batch as Batch from .image import Image as Image from .model import Model as Model from .skill import Skill as Skill from .video import Video as Video from .shared import ( Metadata as Metadata, AllModels as AllModels, ChatModel as ChatModel, Reasoning as Reasoning, ErrorObject as ErrorObject, CompoundFilter as CompoundFilter, ResponsesModel as ResponsesModel, ReasoningEffort as ReasoningEffort, ComparisonFilter as ComparisonFilter, FunctionDefinition as FunctionDefinition, FunctionParameters as FunctionParameters, ResponseFormatText as ResponseFormatText, CustomToolInputFormat as CustomToolInputFormat, ResponseFormatJSONObject as ResponseFormatJSONObject, ResponseFormatJSONSchema as ResponseFormatJSONSchema, ResponseFormatTextPython as ResponseFormatTextPython, ResponseFormatTextGrammar as ResponseFormatTextGrammar, ) from .upload import Upload as Upload from .embedding import Embedding as Embedding from .chat_model import ChatModel as ChatModel from .completion import Completion as Completion from .moderation import Moderation as Moderation from .skill_list import SkillList as SkillList from .video_size import VideoSize as VideoSize from .audio_model import AudioModel as AudioModel from .batch_error import BatchError as BatchError from .batch_usage import BatchUsage as BatchUsage from .file_object import FileObject as FileObject from .image_model import ImageModel as ImageModel from .video_model import VideoModel as VideoModel from .file_content import FileContent as FileContent from .file_deleted import FileDeleted as FileDeleted from .file_purpose import FilePurpose as FilePurpose from .vector_store import VectorStore as VectorStore from .deleted_skill import DeletedSkill as DeletedSkill from .model_deleted import ModelDeleted as ModelDeleted from .video_seconds import VideoSeconds as VideoSeconds from .embedding_model import EmbeddingModel as EmbeddingModel from .images_response import ImagesResponse as ImagesResponse from .completion_usage import CompletionUsage as CompletionUsage from .eval_list_params import EvalListParams as EvalListParams from .file_list_params import FileListParams as FileListParams from .moderation_model import ModerationModel as ModerationModel from .batch_list_params import BatchListParams as BatchListParams from .completion_choice import CompletionChoice as CompletionChoice from .image_edit_params import ImageEditParams as ImageEditParams from .skill_list_params import SkillListParams as SkillListParams from .video_edit_params import VideoEditParams as VideoEditParams from .video_list_params import VideoListParams as VideoListParams from .video_model_param import VideoModelParam as VideoModelParam from .eval_create_params import EvalCreateParams as EvalCreateParams from .eval_list_response import EvalListResponse as EvalListResponse from .eval_update_params import EvalUpdateParams as EvalUpdateParams from .file_create_params import FileCreateParams as FileCreateParams from .video_create_error import VideoCreateError as VideoCreateError from .video_remix_params import VideoRemixParams as VideoRemixParams from .batch_create_params import BatchCreateParams as BatchCreateParams from .skill_create_params import SkillCreateParams as SkillCreateParams from .skill_update_params import SkillUpdateParams as SkillUpdateParams from .video_create_params import VideoCreateParams as VideoCreateParams from .video_extend_params import VideoExtendParams as VideoExtendParams from .batch_request_counts import BatchRequestCounts as BatchRequestCounts from .eval_create_response import EvalCreateResponse as EvalCreateResponse from .eval_delete_response import EvalDeleteResponse as EvalDeleteResponse from .eval_update_response import EvalUpdateResponse as EvalUpdateResponse from .upload_create_params import UploadCreateParams as UploadCreateParams from .vector_store_deleted import VectorStoreDeleted as VectorStoreDeleted from .audio_response_format import AudioResponseFormat as AudioResponseFormat from .container_list_params import ContainerListParams as ContainerListParams from .image_generate_params import ImageGenerateParams as ImageGenerateParams from .video_delete_response import VideoDeleteResponse as VideoDeleteResponse from .eval_retrieve_response import EvalRetrieveResponse as EvalRetrieveResponse from .file_chunking_strategy import FileChunkingStrategy as FileChunkingStrategy from .image_gen_stream_event import ImageGenStreamEvent as ImageGenStreamEvent from .upload_complete_params import UploadCompleteParams as UploadCompleteParams from .container_create_params import ContainerCreateParams as ContainerCreateParams from .container_list_response import ContainerListResponse as ContainerListResponse from .embedding_create_params import EmbeddingCreateParams as EmbeddingCreateParams from .image_edit_stream_event import ImageEditStreamEvent as ImageEditStreamEvent from .completion_create_params import CompletionCreateParams as CompletionCreateParams from .moderation_create_params import ModerationCreateParams as ModerationCreateParams from .vector_store_list_params import VectorStoreListParams as VectorStoreListParams from .container_create_response import ContainerCreateResponse as ContainerCreateResponse from .create_embedding_response import CreateEmbeddingResponse as CreateEmbeddingResponse from .image_gen_completed_event import ImageGenCompletedEvent as ImageGenCompletedEvent from .image_edit_completed_event import ImageEditCompletedEvent as ImageEditCompletedEvent from .moderation_create_response import ModerationCreateResponse as ModerationCreateResponse from .vector_store_create_params import VectorStoreCreateParams as VectorStoreCreateParams from .vector_store_search_params import VectorStoreSearchParams as VectorStoreSearchParams from .vector_store_update_params import VectorStoreUpdateParams as VectorStoreUpdateParams from .container_retrieve_response import ContainerRetrieveResponse as ContainerRetrieveResponse from .image_input_reference_param import ImageInputReferenceParam as ImageInputReferenceParam from .moderation_text_input_param import ModerationTextInputParam as ModerationTextInputParam from .file_chunking_strategy_param import FileChunkingStrategyParam as FileChunkingStrategyParam from .vector_store_search_response import VectorStoreSearchResponse as VectorStoreSearchResponse from .video_get_character_response import VideoGetCharacterResponse as VideoGetCharacterResponse from .websocket_connection_options import ( WebSocketConnectionOptions as WebSocketConnectionOptions, WebsocketConnectionOptions as WebsocketConnectionOptions, ) from .image_create_variation_params import ImageCreateVariationParams as ImageCreateVariationParams from .image_gen_partial_image_event import ImageGenPartialImageEvent as ImageGenPartialImageEvent from .static_file_chunking_strategy import StaticFileChunkingStrategy as StaticFileChunkingStrategy from .video_create_character_params import VideoCreateCharacterParams as VideoCreateCharacterParams from .video_download_content_params import VideoDownloadContentParams as VideoDownloadContentParams from .eval_custom_data_source_config import EvalCustomDataSourceConfig as EvalCustomDataSourceConfig from .image_edit_partial_image_event import ImageEditPartialImageEvent as ImageEditPartialImageEvent from .video_create_character_response import VideoCreateCharacterResponse as VideoCreateCharacterResponse from .moderation_image_url_input_param import ModerationImageURLInputParam as ModerationImageURLInputParam from .auto_file_chunking_strategy_param import AutoFileChunkingStrategyParam as AutoFileChunkingStrategyParam from .moderation_multi_modal_input_param import ModerationMultiModalInputParam as ModerationMultiModalInputParam from .other_file_chunking_strategy_object import OtherFileChunkingStrategyObject as OtherFileChunkingStrategyObject from .static_file_chunking_strategy_param import StaticFileChunkingStrategyParam as StaticFileChunkingStrategyParam from .static_file_chunking_strategy_object import StaticFileChunkingStrategyObject as StaticFileChunkingStrategyObject from .eval_stored_completions_data_source_config import ( EvalStoredCompletionsDataSourceConfig as EvalStoredCompletionsDataSourceConfig, ) from .static_file_chunking_strategy_object_param import ( StaticFileChunkingStrategyObjectParam as StaticFileChunkingStrategyObjectParam, ) ================================================ FILE: src/openai/types/audio/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .translation import Translation as Translation from .speech_model import SpeechModel as SpeechModel from .transcription import Transcription as Transcription from .transcription_word import TranscriptionWord as TranscriptionWord from .translation_verbose import TranslationVerbose as TranslationVerbose from .speech_create_params import SpeechCreateParams as SpeechCreateParams from .transcription_include import TranscriptionInclude as TranscriptionInclude from .transcription_segment import TranscriptionSegment as TranscriptionSegment from .transcription_verbose import TranscriptionVerbose as TranscriptionVerbose from .transcription_diarized import TranscriptionDiarized as TranscriptionDiarized from .translation_create_params import TranslationCreateParams as TranslationCreateParams from .transcription_stream_event import TranscriptionStreamEvent as TranscriptionStreamEvent from .transcription_create_params import TranscriptionCreateParams as TranscriptionCreateParams from .translation_create_response import TranslationCreateResponse as TranslationCreateResponse from .transcription_create_response import TranscriptionCreateResponse as TranscriptionCreateResponse from .transcription_text_done_event import TranscriptionTextDoneEvent as TranscriptionTextDoneEvent from .transcription_diarized_segment import TranscriptionDiarizedSegment as TranscriptionDiarizedSegment from .transcription_text_delta_event import TranscriptionTextDeltaEvent as TranscriptionTextDeltaEvent from .transcription_text_segment_event import TranscriptionTextSegmentEvent as TranscriptionTextSegmentEvent ================================================ FILE: src/openai/types/audio/speech_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, Required, TypeAlias, TypedDict from .speech_model import SpeechModel __all__ = ["SpeechCreateParams", "Voice", "VoiceID"] class SpeechCreateParams(TypedDict, total=False): input: Required[str] """The text to generate audio for. The maximum length is 4096 characters.""" model: Required[Union[str, SpeechModel]] """ One of the available [TTS models](https://platform.openai.com/docs/models#tts): `tts-1`, `tts-1-hd`, `gpt-4o-mini-tts`, or `gpt-4o-mini-tts-2025-12-15`. """ voice: Required[Voice] """The voice to use when generating the audio. Supported built-in voices are `alloy`, `ash`, `ballad`, `coral`, `echo`, `fable`, `onyx`, `nova`, `sage`, `shimmer`, `verse`, `marin`, and `cedar`. You may also provide a custom voice object with an `id`, for example `{ "id": "voice_1234" }`. Previews of the voices are available in the [Text to speech guide](https://platform.openai.com/docs/guides/text-to-speech#voice-options). """ instructions: str """Control the voice of your generated audio with additional instructions. Does not work with `tts-1` or `tts-1-hd`. """ response_format: Literal["mp3", "opus", "aac", "flac", "wav", "pcm"] """The format to audio in. Supported formats are `mp3`, `opus`, `aac`, `flac`, `wav`, and `pcm`. """ speed: float """The speed of the generated audio. Select a value from `0.25` to `4.0`. `1.0` is the default. """ stream_format: Literal["sse", "audio"] """The format to stream the audio in. Supported formats are `sse` and `audio`. `sse` is not supported for `tts-1` or `tts-1-hd`. """ class VoiceID(TypedDict, total=False): """Custom voice reference.""" id: Required[str] """The custom voice ID, e.g. `voice_1234`.""" Voice: TypeAlias = Union[ str, Literal["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse", "marin", "cedar"], VoiceID ] ================================================ FILE: src/openai/types/audio/speech_model.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["SpeechModel"] SpeechModel: TypeAlias = Literal["tts-1", "tts-1-hd", "gpt-4o-mini-tts", "gpt-4o-mini-tts-2025-12-15"] ================================================ FILE: src/openai/types/audio/transcription.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = ["Transcription", "Logprob", "Usage", "UsageTokens", "UsageTokensInputTokenDetails", "UsageDuration"] class Logprob(BaseModel): token: Optional[str] = None """The token in the transcription.""" bytes: Optional[List[float]] = None """The bytes of the token.""" logprob: Optional[float] = None """The log probability of the token.""" class UsageTokensInputTokenDetails(BaseModel): """Details about the input tokens billed for this request.""" audio_tokens: Optional[int] = None """Number of audio tokens billed for this request.""" text_tokens: Optional[int] = None """Number of text tokens billed for this request.""" class UsageTokens(BaseModel): """Usage statistics for models billed by token usage.""" input_tokens: int """Number of input tokens billed for this request.""" output_tokens: int """Number of output tokens generated.""" total_tokens: int """Total number of tokens used (input + output).""" type: Literal["tokens"] """The type of the usage object. Always `tokens` for this variant.""" input_token_details: Optional[UsageTokensInputTokenDetails] = None """Details about the input tokens billed for this request.""" class UsageDuration(BaseModel): """Usage statistics for models billed by audio input duration.""" seconds: float """Duration of the input audio in seconds.""" type: Literal["duration"] """The type of the usage object. Always `duration` for this variant.""" Usage: TypeAlias = Annotated[Union[UsageTokens, UsageDuration], PropertyInfo(discriminator="type")] class Transcription(BaseModel): """ Represents a transcription response returned by model, based on the provided input. """ text: str """The transcribed text.""" logprobs: Optional[List[Logprob]] = None """The log probabilities of the tokens in the transcription. Only returned with the models `gpt-4o-transcribe` and `gpt-4o-mini-transcribe` if `logprobs` is added to the `include` array. """ usage: Optional[Usage] = None """Token usage statistics for the request.""" ================================================ FILE: src/openai/types/audio/transcription_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List, Union, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import FileTypes, SequenceNotStr from ..audio_model import AudioModel from .transcription_include import TranscriptionInclude from ..audio_response_format import AudioResponseFormat __all__ = [ "TranscriptionCreateParamsBase", "ChunkingStrategy", "ChunkingStrategyVadConfig", "TranscriptionCreateParamsNonStreaming", "TranscriptionCreateParamsStreaming", ] class TranscriptionCreateParamsBase(TypedDict, total=False): file: Required[FileTypes] """ The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm. """ model: Required[Union[str, AudioModel]] """ID of the model to use. The options are `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `whisper-1` (which is powered by our open source Whisper V2 model), and `gpt-4o-transcribe-diarize`. """ chunking_strategy: Optional[ChunkingStrategy] """Controls how the audio is cut into chunks. When set to `"auto"`, the server first normalizes loudness and then uses voice activity detection (VAD) to choose boundaries. `server_vad` object can be provided to tweak VAD detection parameters manually. If unset, the audio is transcribed as a single block. Required when using `gpt-4o-transcribe-diarize` for inputs longer than 30 seconds. """ include: List[TranscriptionInclude] """ Additional information to include in the transcription response. `logprobs` will return the log probabilities of the tokens in the response to understand the model's confidence in the transcription. `logprobs` only works with response_format set to `json` and only with the models `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, and `gpt-4o-mini-transcribe-2025-12-15`. This field is not supported when using `gpt-4o-transcribe-diarize`. """ known_speaker_names: SequenceNotStr[str] """ Optional list of speaker names that correspond to the audio samples provided in `known_speaker_references[]`. Each entry should be a short identifier (for example `customer` or `agent`). Up to 4 speakers are supported. """ known_speaker_references: SequenceNotStr[str] """ Optional list of audio samples (as [data URLs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs)) that contain known speaker references matching `known_speaker_names[]`. Each sample must be between 2 and 10 seconds, and can use any of the same input audio formats supported by `file`. """ language: str """The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format will improve accuracy and latency. """ prompt: str """An optional text to guide the model's style or continue a previous audio segment. The [prompt](https://platform.openai.com/docs/guides/speech-to-text#prompting) should match the audio language. This field is not supported when using `gpt-4o-transcribe-diarize`. """ response_format: AudioResponseFormat """ The format of the output, in one of these options: `json`, `text`, `srt`, `verbose_json`, `vtt`, or `diarized_json`. For `gpt-4o-transcribe` and `gpt-4o-mini-transcribe`, the only supported format is `json`. For `gpt-4o-transcribe-diarize`, the supported formats are `json`, `text`, and `diarized_json`, with `diarized_json` required to receive speaker annotations. """ temperature: float """The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit. """ timestamp_granularities: List[Literal["word", "segment"]] """The timestamp granularities to populate for this transcription. `response_format` must be set `verbose_json` to use timestamp granularities. Either or both of these options are supported: `word`, or `segment`. Note: There is no additional latency for segment timestamps, but generating word timestamps incurs additional latency. This option is not available for `gpt-4o-transcribe-diarize`. """ class ChunkingStrategyVadConfig(TypedDict, total=False): type: Required[Literal["server_vad"]] """Must be set to `server_vad` to enable manual chunking using server side VAD.""" prefix_padding_ms: int """Amount of audio to include before the VAD detected speech (in milliseconds).""" silence_duration_ms: int """ Duration of silence to detect speech stop (in milliseconds). With shorter values the model will respond more quickly, but may jump in on short pauses from the user. """ threshold: float """Sensitivity threshold (0.0 to 1.0) for voice activity detection. A higher threshold will require louder audio to activate the model, and thus might perform better in noisy environments. """ ChunkingStrategy: TypeAlias = Union[Literal["auto"], ChunkingStrategyVadConfig] class TranscriptionCreateParamsNonStreaming(TranscriptionCreateParamsBase, total=False): stream: Optional[Literal[False]] """ If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section of the Speech-to-Text guide](https://platform.openai.com/docs/guides/speech-to-text?lang=curl#streaming-transcriptions) for more information. Note: Streaming is not supported for the `whisper-1` model and will be ignored. """ class TranscriptionCreateParamsStreaming(TranscriptionCreateParamsBase): stream: Required[Literal[True]] """ If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section of the Speech-to-Text guide](https://platform.openai.com/docs/guides/speech-to-text?lang=curl#streaming-transcriptions) for more information. Note: Streaming is not supported for the `whisper-1` model and will be ignored. """ TranscriptionCreateParams = Union[TranscriptionCreateParamsNonStreaming, TranscriptionCreateParamsStreaming] ================================================ FILE: src/openai/types/audio/transcription_create_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import TypeAlias from .transcription import Transcription from .transcription_verbose import TranscriptionVerbose from .transcription_diarized import TranscriptionDiarized __all__ = ["TranscriptionCreateResponse"] TranscriptionCreateResponse: TypeAlias = Union[Transcription, TranscriptionDiarized, TranscriptionVerbose] ================================================ FILE: src/openai/types/audio/transcription_diarized.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .transcription_diarized_segment import TranscriptionDiarizedSegment __all__ = ["TranscriptionDiarized", "Usage", "UsageTokens", "UsageTokensInputTokenDetails", "UsageDuration"] class UsageTokensInputTokenDetails(BaseModel): """Details about the input tokens billed for this request.""" audio_tokens: Optional[int] = None """Number of audio tokens billed for this request.""" text_tokens: Optional[int] = None """Number of text tokens billed for this request.""" class UsageTokens(BaseModel): """Usage statistics for models billed by token usage.""" input_tokens: int """Number of input tokens billed for this request.""" output_tokens: int """Number of output tokens generated.""" total_tokens: int """Total number of tokens used (input + output).""" type: Literal["tokens"] """The type of the usage object. Always `tokens` for this variant.""" input_token_details: Optional[UsageTokensInputTokenDetails] = None """Details about the input tokens billed for this request.""" class UsageDuration(BaseModel): """Usage statistics for models billed by audio input duration.""" seconds: float """Duration of the input audio in seconds.""" type: Literal["duration"] """The type of the usage object. Always `duration` for this variant.""" Usage: TypeAlias = Annotated[Union[UsageTokens, UsageDuration], PropertyInfo(discriminator="type")] class TranscriptionDiarized(BaseModel): """ Represents a diarized transcription response returned by the model, including the combined transcript and speaker-segment annotations. """ duration: float """Duration of the input audio in seconds.""" segments: List[TranscriptionDiarizedSegment] """Segments of the transcript annotated with timestamps and speaker labels.""" task: Literal["transcribe"] """The type of task that was run. Always `transcribe`.""" text: str """The concatenated transcript text for the entire audio input.""" usage: Optional[Usage] = None """Token or duration usage statistics for the request.""" ================================================ FILE: src/openai/types/audio/transcription_diarized_segment.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["TranscriptionDiarizedSegment"] class TranscriptionDiarizedSegment(BaseModel): """A segment of diarized transcript text with speaker metadata.""" id: str """Unique identifier for the segment.""" end: float """End timestamp of the segment in seconds.""" speaker: str """Speaker label for this segment. When known speakers are provided, the label matches `known_speaker_names[]`. Otherwise speakers are labeled sequentially using capital letters (`A`, `B`, ...). """ start: float """Start timestamp of the segment in seconds.""" text: str """Transcript text for this segment.""" type: Literal["transcript.text.segment"] """The type of the segment. Always `transcript.text.segment`.""" ================================================ FILE: src/openai/types/audio/transcription_include.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["TranscriptionInclude"] TranscriptionInclude: TypeAlias = Literal["logprobs"] ================================================ FILE: src/openai/types/audio/transcription_segment.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List from ..._models import BaseModel __all__ = ["TranscriptionSegment"] class TranscriptionSegment(BaseModel): id: int """Unique identifier of the segment.""" avg_logprob: float """Average logprob of the segment. If the value is lower than -1, consider the logprobs failed. """ compression_ratio: float """Compression ratio of the segment. If the value is greater than 2.4, consider the compression failed. """ end: float """End time of the segment in seconds.""" no_speech_prob: float """Probability of no speech in the segment. If the value is higher than 1.0 and the `avg_logprob` is below -1, consider this segment silent. """ seek: int """Seek offset of the segment.""" start: float """Start time of the segment in seconds.""" temperature: float """Temperature parameter used for generating the segment.""" text: str """Text content of the segment.""" tokens: List[int] """Array of token IDs for the text content.""" ================================================ FILE: src/openai/types/audio/transcription_stream_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from ..._utils import PropertyInfo from .transcription_text_done_event import TranscriptionTextDoneEvent from .transcription_text_delta_event import TranscriptionTextDeltaEvent from .transcription_text_segment_event import TranscriptionTextSegmentEvent __all__ = ["TranscriptionStreamEvent"] TranscriptionStreamEvent: TypeAlias = Annotated[ Union[TranscriptionTextSegmentEvent, TranscriptionTextDeltaEvent, TranscriptionTextDoneEvent], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/types/audio/transcription_text_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["TranscriptionTextDeltaEvent", "Logprob"] class Logprob(BaseModel): token: Optional[str] = None """The token that was used to generate the log probability.""" bytes: Optional[List[int]] = None """The bytes that were used to generate the log probability.""" logprob: Optional[float] = None """The log probability of the token.""" class TranscriptionTextDeltaEvent(BaseModel): """Emitted when there is an additional text delta. This is also the first event emitted when the transcription starts. Only emitted when you [create a transcription](https://platform.openai.com/docs/api-reference/audio/create-transcription) with the `Stream` parameter set to `true`. """ delta: str """The text delta that was additionally transcribed.""" type: Literal["transcript.text.delta"] """The type of the event. Always `transcript.text.delta`.""" logprobs: Optional[List[Logprob]] = None """The log probabilities of the delta. Only included if you [create a transcription](https://platform.openai.com/docs/api-reference/audio/create-transcription) with the `include[]` parameter set to `logprobs`. """ segment_id: Optional[str] = None """Identifier of the diarized segment that this delta belongs to. Only present when using `gpt-4o-transcribe-diarize`. """ ================================================ FILE: src/openai/types/audio/transcription_text_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["TranscriptionTextDoneEvent", "Logprob", "Usage", "UsageInputTokenDetails"] class Logprob(BaseModel): token: Optional[str] = None """The token that was used to generate the log probability.""" bytes: Optional[List[int]] = None """The bytes that were used to generate the log probability.""" logprob: Optional[float] = None """The log probability of the token.""" class UsageInputTokenDetails(BaseModel): """Details about the input tokens billed for this request.""" audio_tokens: Optional[int] = None """Number of audio tokens billed for this request.""" text_tokens: Optional[int] = None """Number of text tokens billed for this request.""" class Usage(BaseModel): """Usage statistics for models billed by token usage.""" input_tokens: int """Number of input tokens billed for this request.""" output_tokens: int """Number of output tokens generated.""" total_tokens: int """Total number of tokens used (input + output).""" type: Literal["tokens"] """The type of the usage object. Always `tokens` for this variant.""" input_token_details: Optional[UsageInputTokenDetails] = None """Details about the input tokens billed for this request.""" class TranscriptionTextDoneEvent(BaseModel): """Emitted when the transcription is complete. Contains the complete transcription text. Only emitted when you [create a transcription](https://platform.openai.com/docs/api-reference/audio/create-transcription) with the `Stream` parameter set to `true`. """ text: str """The text that was transcribed.""" type: Literal["transcript.text.done"] """The type of the event. Always `transcript.text.done`.""" logprobs: Optional[List[Logprob]] = None """The log probabilities of the individual tokens in the transcription. Only included if you [create a transcription](https://platform.openai.com/docs/api-reference/audio/create-transcription) with the `include[]` parameter set to `logprobs`. """ usage: Optional[Usage] = None """Usage statistics for models billed by token usage.""" ================================================ FILE: src/openai/types/audio/transcription_text_segment_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["TranscriptionTextSegmentEvent"] class TranscriptionTextSegmentEvent(BaseModel): """ Emitted when a diarized transcription returns a completed segment with speaker information. Only emitted when you [create a transcription](https://platform.openai.com/docs/api-reference/audio/create-transcription) with `stream` set to `true` and `response_format` set to `diarized_json`. """ id: str """Unique identifier for the segment.""" end: float """End timestamp of the segment in seconds.""" speaker: str """Speaker label for this segment.""" start: float """Start timestamp of the segment in seconds.""" text: str """Transcript text for this segment.""" type: Literal["transcript.text.segment"] """The type of the event. Always `transcript.text.segment`.""" ================================================ FILE: src/openai/types/audio/transcription_verbose.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel from .transcription_word import TranscriptionWord from .transcription_segment import TranscriptionSegment __all__ = ["TranscriptionVerbose", "Usage"] class Usage(BaseModel): """Usage statistics for models billed by audio input duration.""" seconds: float """Duration of the input audio in seconds.""" type: Literal["duration"] """The type of the usage object. Always `duration` for this variant.""" class TranscriptionVerbose(BaseModel): """ Represents a verbose json transcription response returned by model, based on the provided input. """ duration: float """The duration of the input audio.""" language: str """The language of the input audio.""" text: str """The transcribed text.""" segments: Optional[List[TranscriptionSegment]] = None """Segments of the transcribed text and their corresponding details.""" usage: Optional[Usage] = None """Usage statistics for models billed by audio input duration.""" words: Optional[List[TranscriptionWord]] = None """Extracted words and their corresponding timestamps.""" ================================================ FILE: src/openai/types/audio/transcription_word.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from ..._models import BaseModel __all__ = ["TranscriptionWord"] class TranscriptionWord(BaseModel): end: float """End time of the word in seconds.""" start: float """Start time of the word in seconds.""" word: str """The text content of the word.""" ================================================ FILE: src/openai/types/audio/translation.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from ..._models import BaseModel __all__ = ["Translation"] class Translation(BaseModel): text: str ================================================ FILE: src/openai/types/audio/translation_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, Required, TypedDict from ..._types import FileTypes from ..audio_model import AudioModel __all__ = ["TranslationCreateParams"] class TranslationCreateParams(TypedDict, total=False): file: Required[FileTypes] """ The audio file object (not file name) translate, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm. """ model: Required[Union[str, AudioModel]] """ID of the model to use. Only `whisper-1` (which is powered by our open source Whisper V2 model) is currently available. """ prompt: str """An optional text to guide the model's style or continue a previous audio segment. The [prompt](https://platform.openai.com/docs/guides/speech-to-text#prompting) should be in English. """ response_format: Literal["json", "text", "srt", "verbose_json", "vtt"] """ The format of the output, in one of these options: `json`, `text`, `srt`, `verbose_json`, or `vtt`. """ temperature: float """The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit. """ ================================================ FILE: src/openai/types/audio/translation_create_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import TypeAlias from .translation import Translation from .translation_verbose import TranslationVerbose __all__ = ["TranslationCreateResponse"] TranslationCreateResponse: TypeAlias = Union[Translation, TranslationVerbose] ================================================ FILE: src/openai/types/audio/translation_verbose.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from ..._models import BaseModel from .transcription_segment import TranscriptionSegment __all__ = ["TranslationVerbose"] class TranslationVerbose(BaseModel): duration: float """The duration of the input audio.""" language: str """The language of the output translation (always `english`).""" text: str """The translated text.""" segments: Optional[List[TranscriptionSegment]] = None """Segments of the translated text and their corresponding details.""" ================================================ FILE: src/openai/types/audio_model.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["AudioModel"] AudioModel: TypeAlias = Literal[ "whisper-1", "gpt-4o-transcribe", "gpt-4o-mini-transcribe", "gpt-4o-mini-transcribe-2025-12-15", "gpt-4o-transcribe-diarize", ] ================================================ FILE: src/openai/types/audio_response_format.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["AudioResponseFormat"] AudioResponseFormat: TypeAlias = Literal["json", "text", "srt", "verbose_json", "vtt", "diarized_json"] ================================================ FILE: src/openai/types/auto_file_chunking_strategy_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["AutoFileChunkingStrategyParam"] class AutoFileChunkingStrategyParam(TypedDict, total=False): """The default strategy. This strategy currently uses a `max_chunk_size_tokens` of `800` and `chunk_overlap_tokens` of `400`. """ type: Required[Literal["auto"]] """Always `auto`.""" ================================================ FILE: src/openai/types/batch.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from .._models import BaseModel from .batch_error import BatchError from .batch_usage import BatchUsage from .shared.metadata import Metadata from .batch_request_counts import BatchRequestCounts __all__ = ["Batch", "Errors"] class Errors(BaseModel): data: Optional[List[BatchError]] = None object: Optional[str] = None """The object type, which is always `list`.""" class Batch(BaseModel): id: str completion_window: str """The time frame within which the batch should be processed.""" created_at: int """The Unix timestamp (in seconds) for when the batch was created.""" endpoint: str """The OpenAI API endpoint used by the batch.""" input_file_id: str """The ID of the input file for the batch.""" object: Literal["batch"] """The object type, which is always `batch`.""" status: Literal[ "validating", "failed", "in_progress", "finalizing", "completed", "expired", "cancelling", "cancelled" ] """The current status of the batch.""" cancelled_at: Optional[int] = None """The Unix timestamp (in seconds) for when the batch was cancelled.""" cancelling_at: Optional[int] = None """The Unix timestamp (in seconds) for when the batch started cancelling.""" completed_at: Optional[int] = None """The Unix timestamp (in seconds) for when the batch was completed.""" error_file_id: Optional[str] = None """The ID of the file containing the outputs of requests with errors.""" errors: Optional[Errors] = None expired_at: Optional[int] = None """The Unix timestamp (in seconds) for when the batch expired.""" expires_at: Optional[int] = None """The Unix timestamp (in seconds) for when the batch will expire.""" failed_at: Optional[int] = None """The Unix timestamp (in seconds) for when the batch failed.""" finalizing_at: Optional[int] = None """The Unix timestamp (in seconds) for when the batch started finalizing.""" in_progress_at: Optional[int] = None """The Unix timestamp (in seconds) for when the batch started processing.""" metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ model: Optional[str] = None """Model ID used to process the batch, like `gpt-5-2025-08-07`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. """ output_file_id: Optional[str] = None """The ID of the file containing the outputs of successfully executed requests.""" request_counts: Optional[BatchRequestCounts] = None """The request counts for different statuses within the batch.""" usage: Optional[BatchUsage] = None """ Represents token usage details including input tokens, output tokens, a breakdown of output tokens, and the total tokens used. Only populated on batches created after September 7, 2025. """ ================================================ FILE: src/openai/types/batch_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Literal, Required, TypedDict from .shared_params.metadata import Metadata __all__ = ["BatchCreateParams", "OutputExpiresAfter"] class BatchCreateParams(TypedDict, total=False): completion_window: Required[Literal["24h"]] """The time frame within which the batch should be processed. Currently only `24h` is supported. """ endpoint: Required[ Literal[ "/v1/responses", "/v1/chat/completions", "/v1/embeddings", "/v1/completions", "/v1/moderations", "/v1/images/generations", "/v1/images/edits", "/v1/videos", ] ] """The endpoint to be used for all requests in the batch. Currently `/v1/responses`, `/v1/chat/completions`, `/v1/embeddings`, `/v1/completions`, `/v1/moderations`, `/v1/images/generations`, `/v1/images/edits`, and `/v1/videos` are supported. Note that `/v1/embeddings` batches are also restricted to a maximum of 50,000 embedding inputs across all requests in the batch. """ input_file_id: Required[str] """The ID of an uploaded file that contains requests for the new batch. See [upload file](https://platform.openai.com/docs/api-reference/files/create) for how to upload a file. Your input file must be formatted as a [JSONL file](https://platform.openai.com/docs/api-reference/batch/request-input), and must be uploaded with the purpose `batch`. The file can contain up to 50,000 requests, and can be up to 200 MB in size. """ metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ output_expires_after: OutputExpiresAfter """ The expiration policy for the output and/or error file that are generated for a batch. """ class OutputExpiresAfter(TypedDict, total=False): """ The expiration policy for the output and/or error file that are generated for a batch. """ anchor: Required[Literal["created_at"]] """Anchor timestamp after which the expiration policy applies. Supported anchors: `created_at`. Note that the anchor is the file creation time, not the time the batch is created. """ seconds: Required[int] """The number of seconds after the anchor time that the file will expire. Must be between 3600 (1 hour) and 2592000 (30 days). """ ================================================ FILE: src/openai/types/batch_error.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from .._models import BaseModel __all__ = ["BatchError"] class BatchError(BaseModel): code: Optional[str] = None """An error code identifying the error type.""" line: Optional[int] = None """The line number of the input file where the error occurred, if applicable.""" message: Optional[str] = None """A human-readable message providing more details about the error.""" param: Optional[str] = None """The name of the parameter that caused the error, if applicable.""" ================================================ FILE: src/openai/types/batch_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import TypedDict __all__ = ["BatchListParams"] class BatchListParams(TypedDict, total=False): after: str """A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. """ limit: int """A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. """ ================================================ FILE: src/openai/types/batch_request_counts.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .._models import BaseModel __all__ = ["BatchRequestCounts"] class BatchRequestCounts(BaseModel): """The request counts for different statuses within the batch.""" completed: int """Number of requests that have been completed successfully.""" failed: int """Number of requests that have failed.""" total: int """Total number of requests in the batch.""" ================================================ FILE: src/openai/types/batch_usage.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .._models import BaseModel __all__ = ["BatchUsage", "InputTokensDetails", "OutputTokensDetails"] class InputTokensDetails(BaseModel): """A detailed breakdown of the input tokens.""" cached_tokens: int """The number of tokens that were retrieved from the cache. [More on prompt caching](https://platform.openai.com/docs/guides/prompt-caching). """ class OutputTokensDetails(BaseModel): """A detailed breakdown of the output tokens.""" reasoning_tokens: int """The number of reasoning tokens.""" class BatchUsage(BaseModel): """ Represents token usage details including input tokens, output tokens, a breakdown of output tokens, and the total tokens used. Only populated on batches created after September 7, 2025. """ input_tokens: int """The number of input tokens.""" input_tokens_details: InputTokensDetails """A detailed breakdown of the input tokens.""" output_tokens: int """The number of output tokens.""" output_tokens_details: OutputTokensDetails """A detailed breakdown of the output tokens.""" total_tokens: int """The total number of tokens used.""" ================================================ FILE: src/openai/types/beta/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .thread import Thread as Thread from .assistant import Assistant as Assistant from .function_tool import FunctionTool as FunctionTool from .assistant_tool import AssistantTool as AssistantTool from .thread_deleted import ThreadDeleted as ThreadDeleted from .chatkit_workflow import ChatKitWorkflow as ChatKitWorkflow from .file_search_tool import FileSearchTool as FileSearchTool from .assistant_deleted import AssistantDeleted as AssistantDeleted from .function_tool_param import FunctionToolParam as FunctionToolParam from .assistant_tool_param import AssistantToolParam as AssistantToolParam from .thread_create_params import ThreadCreateParams as ThreadCreateParams from .thread_update_params import ThreadUpdateParams as ThreadUpdateParams from .assistant_list_params import AssistantListParams as AssistantListParams from .assistant_tool_choice import AssistantToolChoice as AssistantToolChoice from .code_interpreter_tool import CodeInterpreterTool as CodeInterpreterTool from .assistant_stream_event import AssistantStreamEvent as AssistantStreamEvent from .file_search_tool_param import FileSearchToolParam as FileSearchToolParam from .assistant_create_params import AssistantCreateParams as AssistantCreateParams from .assistant_update_params import AssistantUpdateParams as AssistantUpdateParams from .assistant_tool_choice_param import AssistantToolChoiceParam as AssistantToolChoiceParam from .code_interpreter_tool_param import CodeInterpreterToolParam as CodeInterpreterToolParam from .assistant_tool_choice_option import AssistantToolChoiceOption as AssistantToolChoiceOption from .thread_create_and_run_params import ThreadCreateAndRunParams as ThreadCreateAndRunParams from .assistant_tool_choice_function import AssistantToolChoiceFunction as AssistantToolChoiceFunction from .assistant_response_format_option import AssistantResponseFormatOption as AssistantResponseFormatOption from .assistant_tool_choice_option_param import AssistantToolChoiceOptionParam as AssistantToolChoiceOptionParam from .assistant_tool_choice_function_param import AssistantToolChoiceFunctionParam as AssistantToolChoiceFunctionParam from .assistant_response_format_option_param import ( AssistantResponseFormatOptionParam as AssistantResponseFormatOptionParam, ) ================================================ FILE: src/openai/types/beta/assistant.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel from .assistant_tool import AssistantTool from ..shared.metadata import Metadata from .assistant_response_format_option import AssistantResponseFormatOption __all__ = ["Assistant", "ToolResources", "ToolResourcesCodeInterpreter", "ToolResourcesFileSearch"] class ToolResourcesCodeInterpreter(BaseModel): file_ids: Optional[List[str]] = None """ A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made available to the `code_interpreter`` tool. There can be a maximum of 20 files associated with the tool. """ class ToolResourcesFileSearch(BaseModel): vector_store_ids: Optional[List[str]] = None """ The ID of the [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) attached to this assistant. There can be a maximum of 1 vector store attached to the assistant. """ class ToolResources(BaseModel): """A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. """ code_interpreter: Optional[ToolResourcesCodeInterpreter] = None file_search: Optional[ToolResourcesFileSearch] = None class Assistant(BaseModel): """Represents an `assistant` that can call the model and use tools.""" id: str """The identifier, which can be referenced in API endpoints.""" created_at: int """The Unix timestamp (in seconds) for when the assistant was created.""" description: Optional[str] = None """The description of the assistant. The maximum length is 512 characters.""" instructions: Optional[str] = None """The system instructions that the assistant uses. The maximum length is 256,000 characters. """ metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ model: str """ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models) for descriptions of them. """ name: Optional[str] = None """The name of the assistant. The maximum length is 256 characters.""" object: Literal["assistant"] """The object type, which is always `assistant`.""" tools: List[AssistantTool] """A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `file_search`, or `function`. """ response_format: Optional[AssistantResponseFormatOption] = None """Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. """ temperature: Optional[float] = None """What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. """ tool_resources: Optional[ToolResources] = None """A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. """ top_p: Optional[float] = None """ An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. """ ================================================ FILE: src/openai/types/beta/assistant_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import SequenceNotStr from ..shared.chat_model import ChatModel from .assistant_tool_param import AssistantToolParam from ..shared_params.metadata import Metadata from ..shared.reasoning_effort import ReasoningEffort from .assistant_response_format_option_param import AssistantResponseFormatOptionParam __all__ = [ "AssistantCreateParams", "ToolResources", "ToolResourcesCodeInterpreter", "ToolResourcesFileSearch", "ToolResourcesFileSearchVectorStore", "ToolResourcesFileSearchVectorStoreChunkingStrategy", "ToolResourcesFileSearchVectorStoreChunkingStrategyAuto", "ToolResourcesFileSearchVectorStoreChunkingStrategyStatic", "ToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic", ] class AssistantCreateParams(TypedDict, total=False): model: Required[Union[str, ChatModel]] """ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models) for descriptions of them. """ description: Optional[str] """The description of the assistant. The maximum length is 512 characters.""" instructions: Optional[str] """The system instructions that the assistant uses. The maximum length is 256,000 characters. """ metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ name: Optional[str] """The name of the assistant. The maximum length is 256 characters.""" reasoning_effort: Optional[ReasoningEffort] """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ response_format: Optional[AssistantResponseFormatOptionParam] """Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. """ temperature: Optional[float] """What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. """ tool_resources: Optional[ToolResources] """A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. """ tools: Iterable[AssistantToolParam] """A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `file_search`, or `function`. """ top_p: Optional[float] """ An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. """ class ToolResourcesCodeInterpreter(TypedDict, total=False): file_ids: SequenceNotStr[str] """ A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool. """ class ToolResourcesFileSearchVectorStoreChunkingStrategyAuto(TypedDict, total=False): """The default strategy. This strategy currently uses a `max_chunk_size_tokens` of `800` and `chunk_overlap_tokens` of `400`. """ type: Required[Literal["auto"]] """Always `auto`.""" class ToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic(TypedDict, total=False): chunk_overlap_tokens: Required[int] """The number of tokens that overlap between chunks. The default value is `400`. Note that the overlap must not exceed half of `max_chunk_size_tokens`. """ max_chunk_size_tokens: Required[int] """The maximum number of tokens in each chunk. The default value is `800`. The minimum value is `100` and the maximum value is `4096`. """ class ToolResourcesFileSearchVectorStoreChunkingStrategyStatic(TypedDict, total=False): static: Required[ToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic] type: Required[Literal["static"]] """Always `static`.""" ToolResourcesFileSearchVectorStoreChunkingStrategy: TypeAlias = Union[ ToolResourcesFileSearchVectorStoreChunkingStrategyAuto, ToolResourcesFileSearchVectorStoreChunkingStrategyStatic ] class ToolResourcesFileSearchVectorStore(TypedDict, total=False): chunking_strategy: ToolResourcesFileSearchVectorStoreChunkingStrategy """The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. """ file_ids: SequenceNotStr[str] """ A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to add to the vector store. For vector stores created before Nov 2025, there can be a maximum of 10,000 files in a vector store. For vector stores created starting in Nov 2025, the limit is 100,000,000 files. """ metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ class ToolResourcesFileSearch(TypedDict, total=False): vector_store_ids: SequenceNotStr[str] """ The [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) attached to this assistant. There can be a maximum of 1 vector store attached to the assistant. """ vector_stores: Iterable[ToolResourcesFileSearchVectorStore] """ A helper to create a [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) with file_ids and attach it to this assistant. There can be a maximum of 1 vector store attached to the assistant. """ class ToolResources(TypedDict, total=False): """A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. """ code_interpreter: ToolResourcesCodeInterpreter file_search: ToolResourcesFileSearch ================================================ FILE: src/openai/types/beta/assistant_deleted.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["AssistantDeleted"] class AssistantDeleted(BaseModel): id: str deleted: bool object: Literal["assistant.deleted"] ================================================ FILE: src/openai/types/beta/assistant_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["AssistantListParams"] class AssistantListParams(TypedDict, total=False): after: str """A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. """ before: str """A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. """ limit: int """A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. """ order: Literal["asc", "desc"] """Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. """ ================================================ FILE: src/openai/types/beta/assistant_response_format_option.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Literal, TypeAlias from ..shared.response_format_text import ResponseFormatText from ..shared.response_format_json_object import ResponseFormatJSONObject from ..shared.response_format_json_schema import ResponseFormatJSONSchema __all__ = ["AssistantResponseFormatOption"] AssistantResponseFormatOption: TypeAlias = Union[ Literal["auto"], ResponseFormatText, ResponseFormatJSONObject, ResponseFormatJSONSchema ] ================================================ FILE: src/openai/types/beta/assistant_response_format_option_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, TypeAlias from ..shared_params.response_format_text import ResponseFormatText from ..shared_params.response_format_json_object import ResponseFormatJSONObject from ..shared_params.response_format_json_schema import ResponseFormatJSONSchema __all__ = ["AssistantResponseFormatOptionParam"] AssistantResponseFormatOptionParam: TypeAlias = Union[ Literal["auto"], ResponseFormatText, ResponseFormatJSONObject, ResponseFormatJSONSchema ] ================================================ FILE: src/openai/types/beta/assistant_stream_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from .thread import Thread from ..._utils import PropertyInfo from ..._models import BaseModel from .threads.run import Run from .threads.message import Message from ..shared.error_object import ErrorObject from .threads.runs.run_step import RunStep from .threads.message_delta_event import MessageDeltaEvent from .threads.runs.run_step_delta_event import RunStepDeltaEvent __all__ = [ "AssistantStreamEvent", "ThreadCreated", "ThreadRunCreated", "ThreadRunQueued", "ThreadRunInProgress", "ThreadRunRequiresAction", "ThreadRunCompleted", "ThreadRunIncomplete", "ThreadRunFailed", "ThreadRunCancelling", "ThreadRunCancelled", "ThreadRunExpired", "ThreadRunStepCreated", "ThreadRunStepInProgress", "ThreadRunStepDelta", "ThreadRunStepCompleted", "ThreadRunStepFailed", "ThreadRunStepCancelled", "ThreadRunStepExpired", "ThreadMessageCreated", "ThreadMessageInProgress", "ThreadMessageDelta", "ThreadMessageCompleted", "ThreadMessageIncomplete", "ErrorEvent", ] class ThreadCreated(BaseModel): """ Occurs when a new [thread](https://platform.openai.com/docs/api-reference/threads/object) is created. """ data: Thread """ Represents a thread that contains [messages](https://platform.openai.com/docs/api-reference/messages). """ event: Literal["thread.created"] enabled: Optional[bool] = None """Whether to enable input audio transcription.""" class ThreadRunCreated(BaseModel): """ Occurs when a new [run](https://platform.openai.com/docs/api-reference/runs/object) is created. """ data: Run """ Represents an execution run on a [thread](https://platform.openai.com/docs/api-reference/threads). """ event: Literal["thread.run.created"] class ThreadRunQueued(BaseModel): """ Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) moves to a `queued` status. """ data: Run """ Represents an execution run on a [thread](https://platform.openai.com/docs/api-reference/threads). """ event: Literal["thread.run.queued"] class ThreadRunInProgress(BaseModel): """ Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) moves to an `in_progress` status. """ data: Run """ Represents an execution run on a [thread](https://platform.openai.com/docs/api-reference/threads). """ event: Literal["thread.run.in_progress"] class ThreadRunRequiresAction(BaseModel): """ Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) moves to a `requires_action` status. """ data: Run """ Represents an execution run on a [thread](https://platform.openai.com/docs/api-reference/threads). """ event: Literal["thread.run.requires_action"] class ThreadRunCompleted(BaseModel): """ Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) is completed. """ data: Run """ Represents an execution run on a [thread](https://platform.openai.com/docs/api-reference/threads). """ event: Literal["thread.run.completed"] class ThreadRunIncomplete(BaseModel): """ Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) ends with status `incomplete`. """ data: Run """ Represents an execution run on a [thread](https://platform.openai.com/docs/api-reference/threads). """ event: Literal["thread.run.incomplete"] class ThreadRunFailed(BaseModel): """ Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) fails. """ data: Run """ Represents an execution run on a [thread](https://platform.openai.com/docs/api-reference/threads). """ event: Literal["thread.run.failed"] class ThreadRunCancelling(BaseModel): """ Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) moves to a `cancelling` status. """ data: Run """ Represents an execution run on a [thread](https://platform.openai.com/docs/api-reference/threads). """ event: Literal["thread.run.cancelling"] class ThreadRunCancelled(BaseModel): """ Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) is cancelled. """ data: Run """ Represents an execution run on a [thread](https://platform.openai.com/docs/api-reference/threads). """ event: Literal["thread.run.cancelled"] class ThreadRunExpired(BaseModel): """ Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) expires. """ data: Run """ Represents an execution run on a [thread](https://platform.openai.com/docs/api-reference/threads). """ event: Literal["thread.run.expired"] class ThreadRunStepCreated(BaseModel): """ Occurs when a [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) is created. """ data: RunStep """Represents a step in execution of a run.""" event: Literal["thread.run.step.created"] class ThreadRunStepInProgress(BaseModel): """ Occurs when a [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) moves to an `in_progress` state. """ data: RunStep """Represents a step in execution of a run.""" event: Literal["thread.run.step.in_progress"] class ThreadRunStepDelta(BaseModel): """ Occurs when parts of a [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) are being streamed. """ data: RunStepDeltaEvent """Represents a run step delta i.e. any changed fields on a run step during streaming. """ event: Literal["thread.run.step.delta"] class ThreadRunStepCompleted(BaseModel): """ Occurs when a [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) is completed. """ data: RunStep """Represents a step in execution of a run.""" event: Literal["thread.run.step.completed"] class ThreadRunStepFailed(BaseModel): """ Occurs when a [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) fails. """ data: RunStep """Represents a step in execution of a run.""" event: Literal["thread.run.step.failed"] class ThreadRunStepCancelled(BaseModel): """ Occurs when a [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) is cancelled. """ data: RunStep """Represents a step in execution of a run.""" event: Literal["thread.run.step.cancelled"] class ThreadRunStepExpired(BaseModel): """ Occurs when a [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) expires. """ data: RunStep """Represents a step in execution of a run.""" event: Literal["thread.run.step.expired"] class ThreadMessageCreated(BaseModel): """ Occurs when a [message](https://platform.openai.com/docs/api-reference/messages/object) is created. """ data: Message """ Represents a message within a [thread](https://platform.openai.com/docs/api-reference/threads). """ event: Literal["thread.message.created"] class ThreadMessageInProgress(BaseModel): """ Occurs when a [message](https://platform.openai.com/docs/api-reference/messages/object) moves to an `in_progress` state. """ data: Message """ Represents a message within a [thread](https://platform.openai.com/docs/api-reference/threads). """ event: Literal["thread.message.in_progress"] class ThreadMessageDelta(BaseModel): """ Occurs when parts of a [Message](https://platform.openai.com/docs/api-reference/messages/object) are being streamed. """ data: MessageDeltaEvent """Represents a message delta i.e. any changed fields on a message during streaming. """ event: Literal["thread.message.delta"] class ThreadMessageCompleted(BaseModel): """ Occurs when a [message](https://platform.openai.com/docs/api-reference/messages/object) is completed. """ data: Message """ Represents a message within a [thread](https://platform.openai.com/docs/api-reference/threads). """ event: Literal["thread.message.completed"] class ThreadMessageIncomplete(BaseModel): """ Occurs when a [message](https://platform.openai.com/docs/api-reference/messages/object) ends before it is completed. """ data: Message """ Represents a message within a [thread](https://platform.openai.com/docs/api-reference/threads). """ event: Literal["thread.message.incomplete"] class ErrorEvent(BaseModel): """ Occurs when an [error](https://platform.openai.com/docs/guides/error-codes#api-errors) occurs. This can happen due to an internal server error or a timeout. """ data: ErrorObject event: Literal["error"] AssistantStreamEvent: TypeAlias = Annotated[ Union[ ThreadCreated, ThreadRunCreated, ThreadRunQueued, ThreadRunInProgress, ThreadRunRequiresAction, ThreadRunCompleted, ThreadRunIncomplete, ThreadRunFailed, ThreadRunCancelling, ThreadRunCancelled, ThreadRunExpired, ThreadRunStepCreated, ThreadRunStepInProgress, ThreadRunStepDelta, ThreadRunStepCompleted, ThreadRunStepFailed, ThreadRunStepCancelled, ThreadRunStepExpired, ThreadMessageCreated, ThreadMessageInProgress, ThreadMessageDelta, ThreadMessageCompleted, ThreadMessageIncomplete, ErrorEvent, ], PropertyInfo(discriminator="event"), ] ================================================ FILE: src/openai/types/beta/assistant_tool.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from ..._utils import PropertyInfo from .function_tool import FunctionTool from .file_search_tool import FileSearchTool from .code_interpreter_tool import CodeInterpreterTool __all__ = ["AssistantTool"] AssistantTool: TypeAlias = Annotated[ Union[CodeInterpreterTool, FileSearchTool, FunctionTool], PropertyInfo(discriminator="type") ] ================================================ FILE: src/openai/types/beta/assistant_tool_choice.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel from .assistant_tool_choice_function import AssistantToolChoiceFunction __all__ = ["AssistantToolChoice"] class AssistantToolChoice(BaseModel): """Specifies a tool the model should use. Use to force the model to call a specific tool. """ type: Literal["function", "code_interpreter", "file_search"] """The type of the tool. If type is `function`, the function name must be set""" function: Optional[AssistantToolChoiceFunction] = None ================================================ FILE: src/openai/types/beta/assistant_tool_choice_function.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from ..._models import BaseModel __all__ = ["AssistantToolChoiceFunction"] class AssistantToolChoiceFunction(BaseModel): name: str """The name of the function to call.""" ================================================ FILE: src/openai/types/beta/assistant_tool_choice_function_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Required, TypedDict __all__ = ["AssistantToolChoiceFunctionParam"] class AssistantToolChoiceFunctionParam(TypedDict, total=False): name: Required[str] """The name of the function to call.""" ================================================ FILE: src/openai/types/beta/assistant_tool_choice_option.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Literal, TypeAlias from .assistant_tool_choice import AssistantToolChoice __all__ = ["AssistantToolChoiceOption"] AssistantToolChoiceOption: TypeAlias = Union[Literal["none", "auto", "required"], AssistantToolChoice] ================================================ FILE: src/openai/types/beta/assistant_tool_choice_option_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, TypeAlias from .assistant_tool_choice_param import AssistantToolChoiceParam __all__ = ["AssistantToolChoiceOptionParam"] AssistantToolChoiceOptionParam: TypeAlias = Union[Literal["none", "auto", "required"], AssistantToolChoiceParam] ================================================ FILE: src/openai/types/beta/assistant_tool_choice_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict from .assistant_tool_choice_function_param import AssistantToolChoiceFunctionParam __all__ = ["AssistantToolChoiceParam"] class AssistantToolChoiceParam(TypedDict, total=False): """Specifies a tool the model should use. Use to force the model to call a specific tool. """ type: Required[Literal["function", "code_interpreter", "file_search"]] """The type of the tool. If type is `function`, the function name must be set""" function: AssistantToolChoiceFunctionParam ================================================ FILE: src/openai/types/beta/assistant_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import TypeAlias from .function_tool_param import FunctionToolParam from .file_search_tool_param import FileSearchToolParam from .code_interpreter_tool_param import CodeInterpreterToolParam __all__ = ["AssistantToolParam"] AssistantToolParam: TypeAlias = Union[CodeInterpreterToolParam, FileSearchToolParam, FunctionToolParam] ================================================ FILE: src/openai/types/beta/assistant_update_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable, Optional from typing_extensions import Literal, TypedDict from ..._types import SequenceNotStr from .assistant_tool_param import AssistantToolParam from ..shared_params.metadata import Metadata from ..shared.reasoning_effort import ReasoningEffort from .assistant_response_format_option_param import AssistantResponseFormatOptionParam __all__ = ["AssistantUpdateParams", "ToolResources", "ToolResourcesCodeInterpreter", "ToolResourcesFileSearch"] class AssistantUpdateParams(TypedDict, total=False): description: Optional[str] """The description of the assistant. The maximum length is 512 characters.""" instructions: Optional[str] """The system instructions that the assistant uses. The maximum length is 256,000 characters. """ metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ model: Union[ str, Literal[ "gpt-5", "gpt-5-mini", "gpt-5-nano", "gpt-5-2025-08-07", "gpt-5-mini-2025-08-07", "gpt-5-nano-2025-08-07", "gpt-4.1", "gpt-4.1-mini", "gpt-4.1-nano", "gpt-4.1-2025-04-14", "gpt-4.1-mini-2025-04-14", "gpt-4.1-nano-2025-04-14", "o3-mini", "o3-mini-2025-01-31", "o1", "o1-2024-12-17", "gpt-4o", "gpt-4o-2024-11-20", "gpt-4o-2024-08-06", "gpt-4o-2024-05-13", "gpt-4o-mini", "gpt-4o-mini-2024-07-18", "gpt-4.5-preview", "gpt-4.5-preview-2025-02-27", "gpt-4-turbo", "gpt-4-turbo-2024-04-09", "gpt-4-0125-preview", "gpt-4-turbo-preview", "gpt-4-1106-preview", "gpt-4-vision-preview", "gpt-4", "gpt-4-0314", "gpt-4-0613", "gpt-4-32k", "gpt-4-32k-0314", "gpt-4-32k-0613", "gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-3.5-turbo-0613", "gpt-3.5-turbo-1106", "gpt-3.5-turbo-0125", "gpt-3.5-turbo-16k-0613", ], ] """ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models) for descriptions of them. """ name: Optional[str] """The name of the assistant. The maximum length is 256 characters.""" reasoning_effort: Optional[ReasoningEffort] """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ response_format: Optional[AssistantResponseFormatOptionParam] """Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. """ temperature: Optional[float] """What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. """ tool_resources: Optional[ToolResources] """A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. """ tools: Iterable[AssistantToolParam] """A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `file_search`, or `function`. """ top_p: Optional[float] """ An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. """ class ToolResourcesCodeInterpreter(TypedDict, total=False): file_ids: SequenceNotStr[str] """ Overrides the list of [file](https://platform.openai.com/docs/api-reference/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool. """ class ToolResourcesFileSearch(TypedDict, total=False): vector_store_ids: SequenceNotStr[str] """ Overrides the [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) attached to this assistant. There can be a maximum of 1 vector store attached to the assistant. """ class ToolResources(TypedDict, total=False): """A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. """ code_interpreter: ToolResourcesCodeInterpreter file_search: ToolResourcesFileSearch ================================================ FILE: src/openai/types/beta/chat/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations ================================================ FILE: src/openai/types/beta/chatkit/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .chat_session import ChatSession as ChatSession from .chatkit_thread import ChatKitThread as ChatKitThread from .chatkit_attachment import ChatKitAttachment as ChatKitAttachment from .thread_list_params import ThreadListParams as ThreadListParams from .chat_session_status import ChatSessionStatus as ChatSessionStatus from .chatkit_widget_item import ChatKitWidgetItem as ChatKitWidgetItem from .chat_session_history import ChatSessionHistory as ChatSessionHistory from .session_create_params import SessionCreateParams as SessionCreateParams from .thread_delete_response import ThreadDeleteResponse as ThreadDeleteResponse from .chat_session_file_upload import ChatSessionFileUpload as ChatSessionFileUpload from .chat_session_rate_limits import ChatSessionRateLimits as ChatSessionRateLimits from .chatkit_thread_item_list import ChatKitThreadItemList as ChatKitThreadItemList from .thread_list_items_params import ThreadListItemsParams as ThreadListItemsParams from .chat_session_workflow_param import ChatSessionWorkflowParam as ChatSessionWorkflowParam from .chatkit_response_output_text import ChatKitResponseOutputText as ChatKitResponseOutputText from .chat_session_rate_limits_param import ChatSessionRateLimitsParam as ChatSessionRateLimitsParam from .chat_session_expires_after_param import ChatSessionExpiresAfterParam as ChatSessionExpiresAfterParam from .chatkit_thread_user_message_item import ChatKitThreadUserMessageItem as ChatKitThreadUserMessageItem from .chat_session_chatkit_configuration import ChatSessionChatKitConfiguration as ChatSessionChatKitConfiguration from .chat_session_automatic_thread_titling import ( ChatSessionAutomaticThreadTitling as ChatSessionAutomaticThreadTitling, ) from .chatkit_thread_assistant_message_item import ( ChatKitThreadAssistantMessageItem as ChatKitThreadAssistantMessageItem, ) from .chat_session_chatkit_configuration_param import ( ChatSessionChatKitConfigurationParam as ChatSessionChatKitConfigurationParam, ) ================================================ FILE: src/openai/types/beta/chatkit/chat_session.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel from ..chatkit_workflow import ChatKitWorkflow from .chat_session_status import ChatSessionStatus from .chat_session_rate_limits import ChatSessionRateLimits from .chat_session_chatkit_configuration import ChatSessionChatKitConfiguration __all__ = ["ChatSession"] class ChatSession(BaseModel): """Represents a ChatKit session and its resolved configuration.""" id: str """Identifier for the ChatKit session.""" chatkit_configuration: ChatSessionChatKitConfiguration """Resolved ChatKit feature configuration for the session.""" client_secret: str """Ephemeral client secret that authenticates session requests.""" expires_at: int """Unix timestamp (in seconds) for when the session expires.""" max_requests_per_1_minute: int """Convenience copy of the per-minute request limit.""" object: Literal["chatkit.session"] """Type discriminator that is always `chatkit.session`.""" rate_limits: ChatSessionRateLimits """Resolved rate limit values.""" status: ChatSessionStatus """Current lifecycle state of the session.""" user: str """User identifier associated with the session.""" workflow: ChatKitWorkflow """Workflow metadata for the session.""" ================================================ FILE: src/openai/types/beta/chatkit/chat_session_automatic_thread_titling.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from ...._models import BaseModel __all__ = ["ChatSessionAutomaticThreadTitling"] class ChatSessionAutomaticThreadTitling(BaseModel): """Automatic thread title preferences for the session.""" enabled: bool """Whether automatic thread titling is enabled.""" ================================================ FILE: src/openai/types/beta/chatkit/chat_session_chatkit_configuration.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from ...._models import BaseModel from .chat_session_history import ChatSessionHistory from .chat_session_file_upload import ChatSessionFileUpload from .chat_session_automatic_thread_titling import ChatSessionAutomaticThreadTitling __all__ = ["ChatSessionChatKitConfiguration"] class ChatSessionChatKitConfiguration(BaseModel): """ChatKit configuration for the session.""" automatic_thread_titling: ChatSessionAutomaticThreadTitling """Automatic thread titling preferences.""" file_upload: ChatSessionFileUpload """Upload settings for the session.""" history: ChatSessionHistory """History retention configuration.""" ================================================ FILE: src/openai/types/beta/chatkit/chat_session_chatkit_configuration_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import TypedDict __all__ = ["ChatSessionChatKitConfigurationParam", "AutomaticThreadTitling", "FileUpload", "History"] class AutomaticThreadTitling(TypedDict, total=False): """Configuration for automatic thread titling. When omitted, automatic thread titling is enabled by default. """ enabled: bool """Enable automatic thread title generation. Defaults to true.""" class FileUpload(TypedDict, total=False): """Configuration for upload enablement and limits. When omitted, uploads are disabled by default (max_files 10, max_file_size 512 MB). """ enabled: bool """Enable uploads for this session. Defaults to false.""" max_file_size: int """Maximum size in megabytes for each uploaded file. Defaults to 512 MB, which is the maximum allowable size. """ max_files: int """Maximum number of files that can be uploaded to the session. Defaults to 10.""" class History(TypedDict, total=False): """Configuration for chat history retention. When omitted, history is enabled by default with no limit on recent_threads (null). """ enabled: bool """Enables chat users to access previous ChatKit threads. Defaults to true.""" recent_threads: int """Number of recent ChatKit threads users have access to. Defaults to unlimited when unset. """ class ChatSessionChatKitConfigurationParam(TypedDict, total=False): """Optional per-session configuration settings for ChatKit behavior.""" automatic_thread_titling: AutomaticThreadTitling """Configuration for automatic thread titling. When omitted, automatic thread titling is enabled by default. """ file_upload: FileUpload """Configuration for upload enablement and limits. When omitted, uploads are disabled by default (max_files 10, max_file_size 512 MB). """ history: History """Configuration for chat history retention. When omitted, history is enabled by default with no limit on recent_threads (null). """ ================================================ FILE: src/openai/types/beta/chatkit/chat_session_expires_after_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ChatSessionExpiresAfterParam"] class ChatSessionExpiresAfterParam(TypedDict, total=False): """Controls when the session expires relative to an anchor timestamp.""" anchor: Required[Literal["created_at"]] """Base timestamp used to calculate expiration. Currently fixed to `created_at`.""" seconds: Required[int] """Number of seconds after the anchor when the session expires.""" ================================================ FILE: src/openai/types/beta/chatkit/chat_session_file_upload.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from ...._models import BaseModel __all__ = ["ChatSessionFileUpload"] class ChatSessionFileUpload(BaseModel): """Upload permissions and limits applied to the session.""" enabled: bool """Indicates if uploads are enabled for the session.""" max_file_size: Optional[int] = None """Maximum upload size in megabytes.""" max_files: Optional[int] = None """Maximum number of uploads allowed during the session.""" ================================================ FILE: src/openai/types/beta/chatkit/chat_session_history.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from ...._models import BaseModel __all__ = ["ChatSessionHistory"] class ChatSessionHistory(BaseModel): """History retention preferences returned for the session.""" enabled: bool """Indicates if chat history is persisted for the session.""" recent_threads: Optional[int] = None """Number of prior threads surfaced in history views. Defaults to null when all history is retained. """ ================================================ FILE: src/openai/types/beta/chatkit/chat_session_rate_limits.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from ...._models import BaseModel __all__ = ["ChatSessionRateLimits"] class ChatSessionRateLimits(BaseModel): """Active per-minute request limit for the session.""" max_requests_per_1_minute: int """Maximum allowed requests per one-minute window.""" ================================================ FILE: src/openai/types/beta/chatkit/chat_session_rate_limits_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import TypedDict __all__ = ["ChatSessionRateLimitsParam"] class ChatSessionRateLimitsParam(TypedDict, total=False): """Controls request rate limits for the session.""" max_requests_per_1_minute: int """Maximum number of requests allowed per minute for the session. Defaults to 10.""" ================================================ FILE: src/openai/types/beta/chatkit/chat_session_status.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["ChatSessionStatus"] ChatSessionStatus: TypeAlias = Literal["active", "expired", "cancelled"] ================================================ FILE: src/openai/types/beta/chatkit/chat_session_workflow_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Union from typing_extensions import Required, TypedDict __all__ = ["ChatSessionWorkflowParam", "Tracing"] class Tracing(TypedDict, total=False): """Optional tracing overrides for the workflow invocation. When omitted, tracing is enabled by default. """ enabled: bool """Whether tracing is enabled during the session. Defaults to true.""" class ChatSessionWorkflowParam(TypedDict, total=False): """Workflow reference and overrides applied to the chat session.""" id: Required[str] """Identifier for the workflow invoked by the session.""" state_variables: Dict[str, Union[str, bool, float]] """State variables forwarded to the workflow. Keys may be up to 64 characters, values must be primitive types, and the map defaults to an empty object. """ tracing: Tracing """Optional tracing overrides for the workflow invocation. When omitted, tracing is enabled by default. """ version: str """Specific workflow version to run. Defaults to the latest deployed version.""" ================================================ FILE: src/openai/types/beta/chatkit/chatkit_attachment.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ChatKitAttachment"] class ChatKitAttachment(BaseModel): """Attachment metadata included on thread items.""" id: str """Identifier for the attachment.""" mime_type: str """MIME type of the attachment.""" name: str """Original display name for the attachment.""" preview_url: Optional[str] = None """Preview URL for rendering the attachment inline.""" type: Literal["image", "file"] """Attachment discriminator.""" ================================================ FILE: src/openai/types/beta/chatkit/chatkit_response_output_text.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union from typing_extensions import Literal, Annotated, TypeAlias from ...._utils import PropertyInfo from ...._models import BaseModel __all__ = [ "ChatKitResponseOutputText", "Annotation", "AnnotationFile", "AnnotationFileSource", "AnnotationURL", "AnnotationURLSource", ] class AnnotationFileSource(BaseModel): """File attachment referenced by the annotation.""" filename: str """Filename referenced by the annotation.""" type: Literal["file"] """Type discriminator that is always `file`.""" class AnnotationFile(BaseModel): """Annotation that references an uploaded file.""" source: AnnotationFileSource """File attachment referenced by the annotation.""" type: Literal["file"] """Type discriminator that is always `file` for this annotation.""" class AnnotationURLSource(BaseModel): """URL referenced by the annotation.""" type: Literal["url"] """Type discriminator that is always `url`.""" url: str """URL referenced by the annotation.""" class AnnotationURL(BaseModel): """Annotation that references a URL.""" source: AnnotationURLSource """URL referenced by the annotation.""" type: Literal["url"] """Type discriminator that is always `url` for this annotation.""" Annotation: TypeAlias = Annotated[Union[AnnotationFile, AnnotationURL], PropertyInfo(discriminator="type")] class ChatKitResponseOutputText(BaseModel): """Assistant response text accompanied by optional annotations.""" annotations: List[Annotation] """Ordered list of annotations attached to the response text.""" text: str """Assistant generated text.""" type: Literal["output_text"] """Type discriminator that is always `output_text`.""" ================================================ FILE: src/openai/types/beta/chatkit/chatkit_thread.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ...._utils import PropertyInfo from ...._models import BaseModel __all__ = ["ChatKitThread", "Status", "StatusActive", "StatusLocked", "StatusClosed"] class StatusActive(BaseModel): """Indicates that a thread is active.""" type: Literal["active"] """Status discriminator that is always `active`.""" class StatusLocked(BaseModel): """Indicates that a thread is locked and cannot accept new input.""" reason: Optional[str] = None """Reason that the thread was locked. Defaults to null when no reason is recorded.""" type: Literal["locked"] """Status discriminator that is always `locked`.""" class StatusClosed(BaseModel): """Indicates that a thread has been closed.""" reason: Optional[str] = None """Reason that the thread was closed. Defaults to null when no reason is recorded.""" type: Literal["closed"] """Status discriminator that is always `closed`.""" Status: TypeAlias = Annotated[Union[StatusActive, StatusLocked, StatusClosed], PropertyInfo(discriminator="type")] class ChatKitThread(BaseModel): """Represents a ChatKit thread and its current status.""" id: str """Identifier of the thread.""" created_at: int """Unix timestamp (in seconds) for when the thread was created.""" object: Literal["chatkit.thread"] """Type discriminator that is always `chatkit.thread`.""" status: Status """Current status for the thread. Defaults to `active` for newly created threads.""" title: Optional[str] = None """Optional human-readable title for the thread. Defaults to null when no title has been generated. """ user: str """Free-form string that identifies your end user who owns the thread.""" ================================================ FILE: src/openai/types/beta/chatkit/chatkit_thread_assistant_message_item.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List from typing_extensions import Literal from ...._models import BaseModel from .chatkit_response_output_text import ChatKitResponseOutputText __all__ = ["ChatKitThreadAssistantMessageItem"] class ChatKitThreadAssistantMessageItem(BaseModel): """Assistant-authored message within a thread.""" id: str """Identifier of the thread item.""" content: List[ChatKitResponseOutputText] """Ordered assistant response segments.""" created_at: int """Unix timestamp (in seconds) for when the item was created.""" object: Literal["chatkit.thread_item"] """Type discriminator that is always `chatkit.thread_item`.""" thread_id: str """Identifier of the parent thread.""" type: Literal["chatkit.assistant_message"] """Type discriminator that is always `chatkit.assistant_message`.""" ================================================ FILE: src/openai/types/beta/chatkit/chatkit_thread_item_list.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ...._utils import PropertyInfo from ...._models import BaseModel from .chatkit_widget_item import ChatKitWidgetItem from .chatkit_thread_user_message_item import ChatKitThreadUserMessageItem from .chatkit_thread_assistant_message_item import ChatKitThreadAssistantMessageItem __all__ = [ "ChatKitThreadItemList", "Data", "DataChatKitClientToolCall", "DataChatKitTask", "DataChatKitTaskGroup", "DataChatKitTaskGroupTask", ] class DataChatKitClientToolCall(BaseModel): """Record of a client side tool invocation initiated by the assistant.""" id: str """Identifier of the thread item.""" arguments: str """JSON-encoded arguments that were sent to the tool.""" call_id: str """Identifier for the client tool call.""" created_at: int """Unix timestamp (in seconds) for when the item was created.""" name: str """Tool name that was invoked.""" object: Literal["chatkit.thread_item"] """Type discriminator that is always `chatkit.thread_item`.""" output: Optional[str] = None """JSON-encoded output captured from the tool. Defaults to null while execution is in progress. """ status: Literal["in_progress", "completed"] """Execution status for the tool call.""" thread_id: str """Identifier of the parent thread.""" type: Literal["chatkit.client_tool_call"] """Type discriminator that is always `chatkit.client_tool_call`.""" class DataChatKitTask(BaseModel): """Task emitted by the workflow to show progress and status updates.""" id: str """Identifier of the thread item.""" created_at: int """Unix timestamp (in seconds) for when the item was created.""" heading: Optional[str] = None """Optional heading for the task. Defaults to null when not provided.""" object: Literal["chatkit.thread_item"] """Type discriminator that is always `chatkit.thread_item`.""" summary: Optional[str] = None """Optional summary that describes the task. Defaults to null when omitted.""" task_type: Literal["custom", "thought"] """Subtype for the task.""" thread_id: str """Identifier of the parent thread.""" type: Literal["chatkit.task"] """Type discriminator that is always `chatkit.task`.""" class DataChatKitTaskGroupTask(BaseModel): """Task entry that appears within a TaskGroup.""" heading: Optional[str] = None """Optional heading for the grouped task. Defaults to null when not provided.""" summary: Optional[str] = None """Optional summary that describes the grouped task. Defaults to null when omitted. """ type: Literal["custom", "thought"] """Subtype for the grouped task.""" class DataChatKitTaskGroup(BaseModel): """Collection of workflow tasks grouped together in the thread.""" id: str """Identifier of the thread item.""" created_at: int """Unix timestamp (in seconds) for when the item was created.""" object: Literal["chatkit.thread_item"] """Type discriminator that is always `chatkit.thread_item`.""" tasks: List[DataChatKitTaskGroupTask] """Tasks included in the group.""" thread_id: str """Identifier of the parent thread.""" type: Literal["chatkit.task_group"] """Type discriminator that is always `chatkit.task_group`.""" Data: TypeAlias = Annotated[ Union[ ChatKitThreadUserMessageItem, ChatKitThreadAssistantMessageItem, ChatKitWidgetItem, DataChatKitClientToolCall, DataChatKitTask, DataChatKitTaskGroup, ], PropertyInfo(discriminator="type"), ] class ChatKitThreadItemList(BaseModel): """A paginated list of thread items rendered for the ChatKit API.""" data: List[Data] """A list of items""" first_id: Optional[str] = None """The ID of the first item in the list.""" has_more: bool """Whether there are more items available.""" last_id: Optional[str] = None """The ID of the last item in the list.""" object: Literal["list"] """The type of object returned, must be `list`.""" ================================================ FILE: src/openai/types/beta/chatkit/chatkit_thread_user_message_item.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ...._utils import PropertyInfo from ...._models import BaseModel from .chatkit_attachment import ChatKitAttachment __all__ = [ "ChatKitThreadUserMessageItem", "Content", "ContentInputText", "ContentQuotedText", "InferenceOptions", "InferenceOptionsToolChoice", ] class ContentInputText(BaseModel): """Text block that a user contributed to the thread.""" text: str """Plain-text content supplied by the user.""" type: Literal["input_text"] """Type discriminator that is always `input_text`.""" class ContentQuotedText(BaseModel): """Quoted snippet that the user referenced in their message.""" text: str """Quoted text content.""" type: Literal["quoted_text"] """Type discriminator that is always `quoted_text`.""" Content: TypeAlias = Annotated[Union[ContentInputText, ContentQuotedText], PropertyInfo(discriminator="type")] class InferenceOptionsToolChoice(BaseModel): """Preferred tool to invoke. Defaults to null when ChatKit should auto-select.""" id: str """Identifier of the requested tool.""" class InferenceOptions(BaseModel): """Inference overrides applied to the message. Defaults to null when unset.""" model: Optional[str] = None """Model name that generated the response. Defaults to null when using the session default. """ tool_choice: Optional[InferenceOptionsToolChoice] = None """Preferred tool to invoke. Defaults to null when ChatKit should auto-select.""" class ChatKitThreadUserMessageItem(BaseModel): """User-authored messages within a thread.""" id: str """Identifier of the thread item.""" attachments: List[ChatKitAttachment] """Attachments associated with the user message. Defaults to an empty list.""" content: List[Content] """Ordered content elements supplied by the user.""" created_at: int """Unix timestamp (in seconds) for when the item was created.""" inference_options: Optional[InferenceOptions] = None """Inference overrides applied to the message. Defaults to null when unset.""" object: Literal["chatkit.thread_item"] """Type discriminator that is always `chatkit.thread_item`.""" thread_id: str """Identifier of the parent thread.""" type: Literal["chatkit.user_message"] ================================================ FILE: src/openai/types/beta/chatkit/chatkit_widget_item.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ChatKitWidgetItem"] class ChatKitWidgetItem(BaseModel): """Thread item that renders a widget payload.""" id: str """Identifier of the thread item.""" created_at: int """Unix timestamp (in seconds) for when the item was created.""" object: Literal["chatkit.thread_item"] """Type discriminator that is always `chatkit.thread_item`.""" thread_id: str """Identifier of the parent thread.""" type: Literal["chatkit.widget"] """Type discriminator that is always `chatkit.widget`.""" widget: str """Serialized widget payload rendered in the UI.""" ================================================ FILE: src/openai/types/beta/chatkit/session_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Required, TypedDict from .chat_session_workflow_param import ChatSessionWorkflowParam from .chat_session_rate_limits_param import ChatSessionRateLimitsParam from .chat_session_expires_after_param import ChatSessionExpiresAfterParam from .chat_session_chatkit_configuration_param import ChatSessionChatKitConfigurationParam __all__ = ["SessionCreateParams"] class SessionCreateParams(TypedDict, total=False): user: Required[str] """ A free-form string that identifies your end user; ensures this Session can access other objects that have the same `user` scope. """ workflow: Required[ChatSessionWorkflowParam] """Workflow that powers the session.""" chatkit_configuration: ChatSessionChatKitConfigurationParam """Optional overrides for ChatKit runtime configuration features""" expires_after: ChatSessionExpiresAfterParam """Optional override for session expiration timing in seconds from creation. Defaults to 10 minutes. """ rate_limits: ChatSessionRateLimitsParam """Optional override for per-minute request limits. When omitted, defaults to 10.""" ================================================ FILE: src/openai/types/beta/chatkit/thread_delete_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ThreadDeleteResponse"] class ThreadDeleteResponse(BaseModel): """Confirmation payload returned after deleting a thread.""" id: str """Identifier of the deleted thread.""" deleted: bool """Indicates that the thread has been deleted.""" object: Literal["chatkit.thread.deleted"] """Type discriminator that is always `chatkit.thread.deleted`.""" ================================================ FILE: src/openai/types/beta/chatkit/thread_list_items_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["ThreadListItemsParams"] class ThreadListItemsParams(TypedDict, total=False): after: str """List items created after this thread item ID. Defaults to null for the first page. """ before: str """List items created before this thread item ID. Defaults to null for the newest results. """ limit: int """Maximum number of thread items to return. Defaults to 20.""" order: Literal["asc", "desc"] """Sort order for results by creation time. Defaults to `desc`.""" ================================================ FILE: src/openai/types/beta/chatkit/thread_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["ThreadListParams"] class ThreadListParams(TypedDict, total=False): after: str """List items created after this thread item ID. Defaults to null for the first page. """ before: str """List items created before this thread item ID. Defaults to null for the newest results. """ limit: int """Maximum number of thread items to return. Defaults to 20.""" order: Literal["asc", "desc"] """Sort order for results by creation time. Defaults to `desc`.""" user: str """Filter threads that belong to this user identifier. Defaults to null to return all users. """ ================================================ FILE: src/openai/types/beta/chatkit_workflow.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, Union, Optional from ..._models import BaseModel __all__ = ["ChatKitWorkflow", "Tracing"] class Tracing(BaseModel): """Tracing settings applied to the workflow.""" enabled: bool """Indicates whether tracing is enabled.""" class ChatKitWorkflow(BaseModel): """Workflow metadata and state returned for the session.""" id: str """Identifier of the workflow backing the session.""" state_variables: Optional[Dict[str, Union[str, bool, float]]] = None """State variable key-value pairs applied when invoking the workflow. Defaults to null when no overrides were provided. """ tracing: Tracing """Tracing settings applied to the workflow.""" version: Optional[str] = None """Specific workflow version used for the session. Defaults to null when using the latest deployment. """ ================================================ FILE: src/openai/types/beta/code_interpreter_tool.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["CodeInterpreterTool"] class CodeInterpreterTool(BaseModel): type: Literal["code_interpreter"] """The type of tool being defined: `code_interpreter`""" ================================================ FILE: src/openai/types/beta/code_interpreter_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["CodeInterpreterToolParam"] class CodeInterpreterToolParam(TypedDict, total=False): type: Required[Literal["code_interpreter"]] """The type of tool being defined: `code_interpreter`""" ================================================ FILE: src/openai/types/beta/file_search_tool.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["FileSearchTool", "FileSearch", "FileSearchRankingOptions"] class FileSearchRankingOptions(BaseModel): """The ranking options for the file search. If not specified, the file search tool will use the `auto` ranker and a score_threshold of 0. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) for more information. """ score_threshold: float """The score threshold for the file search. All values must be a floating point number between 0 and 1. """ ranker: Optional[Literal["auto", "default_2024_08_21"]] = None """The ranker to use for the file search. If not specified will use the `auto` ranker. """ class FileSearch(BaseModel): """Overrides for the file search tool.""" max_num_results: Optional[int] = None """The maximum number of results the file search tool should output. The default is 20 for `gpt-4*` models and 5 for `gpt-3.5-turbo`. This number should be between 1 and 50 inclusive. Note that the file search tool may output fewer than `max_num_results` results. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) for more information. """ ranking_options: Optional[FileSearchRankingOptions] = None """The ranking options for the file search. If not specified, the file search tool will use the `auto` ranker and a score_threshold of 0. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) for more information. """ class FileSearchTool(BaseModel): type: Literal["file_search"] """The type of tool being defined: `file_search`""" file_search: Optional[FileSearch] = None """Overrides for the file search tool.""" ================================================ FILE: src/openai/types/beta/file_search_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["FileSearchToolParam", "FileSearch", "FileSearchRankingOptions"] class FileSearchRankingOptions(TypedDict, total=False): """The ranking options for the file search. If not specified, the file search tool will use the `auto` ranker and a score_threshold of 0. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) for more information. """ score_threshold: Required[float] """The score threshold for the file search. All values must be a floating point number between 0 and 1. """ ranker: Literal["auto", "default_2024_08_21"] """The ranker to use for the file search. If not specified will use the `auto` ranker. """ class FileSearch(TypedDict, total=False): """Overrides for the file search tool.""" max_num_results: int """The maximum number of results the file search tool should output. The default is 20 for `gpt-4*` models and 5 for `gpt-3.5-turbo`. This number should be between 1 and 50 inclusive. Note that the file search tool may output fewer than `max_num_results` results. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) for more information. """ ranking_options: FileSearchRankingOptions """The ranking options for the file search. If not specified, the file search tool will use the `auto` ranker and a score_threshold of 0. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) for more information. """ class FileSearchToolParam(TypedDict, total=False): type: Required[Literal["file_search"]] """The type of tool being defined: `file_search`""" file_search: FileSearch """Overrides for the file search tool.""" ================================================ FILE: src/openai/types/beta/function_tool.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel from ..shared.function_definition import FunctionDefinition __all__ = ["FunctionTool"] class FunctionTool(BaseModel): function: FunctionDefinition type: Literal["function"] """The type of tool being defined: `function`""" ================================================ FILE: src/openai/types/beta/function_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict from ..shared_params.function_definition import FunctionDefinition __all__ = ["FunctionToolParam"] class FunctionToolParam(TypedDict, total=False): function: Required[FunctionDefinition] type: Required[Literal["function"]] """The type of tool being defined: `function`""" ================================================ FILE: src/openai/types/beta/realtime/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .session import Session as Session from .error_event import ErrorEvent as ErrorEvent from .conversation_item import ConversationItem as ConversationItem from .realtime_response import RealtimeResponse as RealtimeResponse from .response_done_event import ResponseDoneEvent as ResponseDoneEvent from .session_update_event import SessionUpdateEvent as SessionUpdateEvent from .realtime_client_event import RealtimeClientEvent as RealtimeClientEvent from .realtime_server_event import RealtimeServerEvent as RealtimeServerEvent from .response_cancel_event import ResponseCancelEvent as ResponseCancelEvent from .response_create_event import ResponseCreateEvent as ResponseCreateEvent from .session_create_params import SessionCreateParams as SessionCreateParams from .session_created_event import SessionCreatedEvent as SessionCreatedEvent from .session_updated_event import SessionUpdatedEvent as SessionUpdatedEvent from .transcription_session import TranscriptionSession as TranscriptionSession from .response_created_event import ResponseCreatedEvent as ResponseCreatedEvent from .conversation_item_param import ConversationItemParam as ConversationItemParam from .realtime_connect_params import RealtimeConnectParams as RealtimeConnectParams from .realtime_response_usage import RealtimeResponseUsage as RealtimeResponseUsage from .session_create_response import SessionCreateResponse as SessionCreateResponse from .realtime_response_status import RealtimeResponseStatus as RealtimeResponseStatus from .response_text_done_event import ResponseTextDoneEvent as ResponseTextDoneEvent from .conversation_item_content import ConversationItemContent as ConversationItemContent from .rate_limits_updated_event import RateLimitsUpdatedEvent as RateLimitsUpdatedEvent from .response_audio_done_event import ResponseAudioDoneEvent as ResponseAudioDoneEvent from .response_text_delta_event import ResponseTextDeltaEvent as ResponseTextDeltaEvent from .conversation_created_event import ConversationCreatedEvent as ConversationCreatedEvent from .response_audio_delta_event import ResponseAudioDeltaEvent as ResponseAudioDeltaEvent from .session_update_event_param import SessionUpdateEventParam as SessionUpdateEventParam from .realtime_client_event_param import RealtimeClientEventParam as RealtimeClientEventParam from .response_cancel_event_param import ResponseCancelEventParam as ResponseCancelEventParam from .response_create_event_param import ResponseCreateEventParam as ResponseCreateEventParam from .transcription_session_update import TranscriptionSessionUpdate as TranscriptionSessionUpdate from .conversation_item_create_event import ConversationItemCreateEvent as ConversationItemCreateEvent from .conversation_item_delete_event import ConversationItemDeleteEvent as ConversationItemDeleteEvent from .input_audio_buffer_clear_event import InputAudioBufferClearEvent as InputAudioBufferClearEvent from .conversation_item_content_param import ConversationItemContentParam as ConversationItemContentParam from .conversation_item_created_event import ConversationItemCreatedEvent as ConversationItemCreatedEvent from .conversation_item_deleted_event import ConversationItemDeletedEvent as ConversationItemDeletedEvent from .input_audio_buffer_append_event import InputAudioBufferAppendEvent as InputAudioBufferAppendEvent from .input_audio_buffer_commit_event import InputAudioBufferCommitEvent as InputAudioBufferCommitEvent from .response_output_item_done_event import ResponseOutputItemDoneEvent as ResponseOutputItemDoneEvent from .conversation_item_retrieve_event import ConversationItemRetrieveEvent as ConversationItemRetrieveEvent from .conversation_item_truncate_event import ConversationItemTruncateEvent as ConversationItemTruncateEvent from .conversation_item_with_reference import ConversationItemWithReference as ConversationItemWithReference from .input_audio_buffer_cleared_event import InputAudioBufferClearedEvent as InputAudioBufferClearedEvent from .response_content_part_done_event import ResponseContentPartDoneEvent as ResponseContentPartDoneEvent from .response_output_item_added_event import ResponseOutputItemAddedEvent as ResponseOutputItemAddedEvent from .conversation_item_truncated_event import ConversationItemTruncatedEvent as ConversationItemTruncatedEvent from .response_content_part_added_event import ResponseContentPartAddedEvent as ResponseContentPartAddedEvent from .input_audio_buffer_committed_event import InputAudioBufferCommittedEvent as InputAudioBufferCommittedEvent from .transcription_session_update_param import TranscriptionSessionUpdateParam as TranscriptionSessionUpdateParam from .transcription_session_create_params import TranscriptionSessionCreateParams as TranscriptionSessionCreateParams from .transcription_session_updated_event import TranscriptionSessionUpdatedEvent as TranscriptionSessionUpdatedEvent from .conversation_item_create_event_param import ConversationItemCreateEventParam as ConversationItemCreateEventParam from .conversation_item_delete_event_param import ConversationItemDeleteEventParam as ConversationItemDeleteEventParam from .input_audio_buffer_clear_event_param import InputAudioBufferClearEventParam as InputAudioBufferClearEventParam from .response_audio_transcript_done_event import ResponseAudioTranscriptDoneEvent as ResponseAudioTranscriptDoneEvent from .input_audio_buffer_append_event_param import InputAudioBufferAppendEventParam as InputAudioBufferAppendEventParam from .input_audio_buffer_commit_event_param import InputAudioBufferCommitEventParam as InputAudioBufferCommitEventParam from .response_audio_transcript_delta_event import ( ResponseAudioTranscriptDeltaEvent as ResponseAudioTranscriptDeltaEvent, ) from .conversation_item_retrieve_event_param import ( ConversationItemRetrieveEventParam as ConversationItemRetrieveEventParam, ) from .conversation_item_truncate_event_param import ( ConversationItemTruncateEventParam as ConversationItemTruncateEventParam, ) from .conversation_item_with_reference_param import ( ConversationItemWithReferenceParam as ConversationItemWithReferenceParam, ) from .input_audio_buffer_speech_started_event import ( InputAudioBufferSpeechStartedEvent as InputAudioBufferSpeechStartedEvent, ) from .input_audio_buffer_speech_stopped_event import ( InputAudioBufferSpeechStoppedEvent as InputAudioBufferSpeechStoppedEvent, ) from .response_function_call_arguments_done_event import ( ResponseFunctionCallArgumentsDoneEvent as ResponseFunctionCallArgumentsDoneEvent, ) from .response_function_call_arguments_delta_event import ( ResponseFunctionCallArgumentsDeltaEvent as ResponseFunctionCallArgumentsDeltaEvent, ) from .conversation_item_input_audio_transcription_delta_event import ( ConversationItemInputAudioTranscriptionDeltaEvent as ConversationItemInputAudioTranscriptionDeltaEvent, ) from .conversation_item_input_audio_transcription_failed_event import ( ConversationItemInputAudioTranscriptionFailedEvent as ConversationItemInputAudioTranscriptionFailedEvent, ) from .conversation_item_input_audio_transcription_completed_event import ( ConversationItemInputAudioTranscriptionCompletedEvent as ConversationItemInputAudioTranscriptionCompletedEvent, ) ================================================ FILE: src/openai/types/beta/realtime/conversation_created_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ConversationCreatedEvent", "Conversation"] class Conversation(BaseModel): id: Optional[str] = None """The unique ID of the conversation.""" object: Optional[Literal["realtime.conversation"]] = None """The object type, must be `realtime.conversation`.""" class ConversationCreatedEvent(BaseModel): conversation: Conversation """The conversation resource.""" event_id: str """The unique ID of the server event.""" type: Literal["conversation.created"] """The event type, must be `conversation.created`.""" ================================================ FILE: src/openai/types/beta/realtime/conversation_item.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ...._models import BaseModel from .conversation_item_content import ConversationItemContent __all__ = ["ConversationItem"] class ConversationItem(BaseModel): id: Optional[str] = None """ The unique ID of the item, this can be generated by the client to help manage server-side context, but is not required because the server will generate one if not provided. """ arguments: Optional[str] = None """The arguments of the function call (for `function_call` items).""" call_id: Optional[str] = None """ The ID of the function call (for `function_call` and `function_call_output` items). If passed on a `function_call_output` item, the server will check that a `function_call` item with the same ID exists in the conversation history. """ content: Optional[List[ConversationItemContent]] = None """The content of the message, applicable for `message` items. - Message items of role `system` support only `input_text` content - Message items of role `user` support `input_text` and `input_audio` content - Message items of role `assistant` support `text` content. """ name: Optional[str] = None """The name of the function being called (for `function_call` items).""" object: Optional[Literal["realtime.item"]] = None """Identifier for the API object being returned - always `realtime.item`.""" output: Optional[str] = None """The output of the function call (for `function_call_output` items).""" role: Optional[Literal["user", "assistant", "system"]] = None """ The role of the message sender (`user`, `assistant`, `system`), only applicable for `message` items. """ status: Optional[Literal["completed", "incomplete", "in_progress"]] = None """The status of the item (`completed`, `incomplete`, `in_progress`). These have no effect on the conversation, but are accepted for consistency with the `conversation.item.created` event. """ type: Optional[Literal["message", "function_call", "function_call_output"]] = None """The type of the item (`message`, `function_call`, `function_call_output`).""" ================================================ FILE: src/openai/types/beta/realtime/conversation_item_content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ConversationItemContent"] class ConversationItemContent(BaseModel): id: Optional[str] = None """ ID of a previous conversation item to reference (for `item_reference` content types in `response.create` events). These can reference both client and server created items. """ audio: Optional[str] = None """Base64-encoded audio bytes, used for `input_audio` content type.""" text: Optional[str] = None """The text content, used for `input_text` and `text` content types.""" transcript: Optional[str] = None """The transcript of the audio, used for `input_audio` and `audio` content types.""" type: Optional[Literal["input_text", "input_audio", "item_reference", "text", "audio"]] = None """ The content type (`input_text`, `input_audio`, `item_reference`, `text`, `audio`). """ ================================================ FILE: src/openai/types/beta/realtime/conversation_item_content_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["ConversationItemContentParam"] class ConversationItemContentParam(TypedDict, total=False): id: str """ ID of a previous conversation item to reference (for `item_reference` content types in `response.create` events). These can reference both client and server created items. """ audio: str """Base64-encoded audio bytes, used for `input_audio` content type.""" text: str """The text content, used for `input_text` and `text` content types.""" transcript: str """The transcript of the audio, used for `input_audio` and `audio` content types.""" type: Literal["input_text", "input_audio", "item_reference", "text", "audio"] """ The content type (`input_text`, `input_audio`, `item_reference`, `text`, `audio`). """ ================================================ FILE: src/openai/types/beta/realtime/conversation_item_create_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel from .conversation_item import ConversationItem __all__ = ["ConversationItemCreateEvent"] class ConversationItemCreateEvent(BaseModel): item: ConversationItem """The item to add to the conversation.""" type: Literal["conversation.item.create"] """The event type, must be `conversation.item.create`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" previous_item_id: Optional[str] = None """The ID of the preceding item after which the new item will be inserted. If not set, the new item will be appended to the end of the conversation. If set to `root`, the new item will be added to the beginning of the conversation. If set to an existing ID, it allows an item to be inserted mid-conversation. If the ID cannot be found, an error will be returned and the item will not be added. """ ================================================ FILE: src/openai/types/beta/realtime/conversation_item_create_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict from .conversation_item_param import ConversationItemParam __all__ = ["ConversationItemCreateEventParam"] class ConversationItemCreateEventParam(TypedDict, total=False): item: Required[ConversationItemParam] """The item to add to the conversation.""" type: Required[Literal["conversation.item.create"]] """The event type, must be `conversation.item.create`.""" event_id: str """Optional client-generated ID used to identify this event.""" previous_item_id: str """The ID of the preceding item after which the new item will be inserted. If not set, the new item will be appended to the end of the conversation. If set to `root`, the new item will be added to the beginning of the conversation. If set to an existing ID, it allows an item to be inserted mid-conversation. If the ID cannot be found, an error will be returned and the item will not be added. """ ================================================ FILE: src/openai/types/beta/realtime/conversation_item_created_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel from .conversation_item import ConversationItem __all__ = ["ConversationItemCreatedEvent"] class ConversationItemCreatedEvent(BaseModel): event_id: str """The unique ID of the server event.""" item: ConversationItem """The item to add to the conversation.""" type: Literal["conversation.item.created"] """The event type, must be `conversation.item.created`.""" previous_item_id: Optional[str] = None """ The ID of the preceding item in the Conversation context, allows the client to understand the order of the conversation. Can be `null` if the item has no predecessor. """ ================================================ FILE: src/openai/types/beta/realtime/conversation_item_delete_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ConversationItemDeleteEvent"] class ConversationItemDeleteEvent(BaseModel): item_id: str """The ID of the item to delete.""" type: Literal["conversation.item.delete"] """The event type, must be `conversation.item.delete`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/beta/realtime/conversation_item_delete_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ConversationItemDeleteEventParam"] class ConversationItemDeleteEventParam(TypedDict, total=False): item_id: Required[str] """The ID of the item to delete.""" type: Required[Literal["conversation.item.delete"]] """The event type, must be `conversation.item.delete`.""" event_id: str """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/beta/realtime/conversation_item_deleted_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ConversationItemDeletedEvent"] class ConversationItemDeletedEvent(BaseModel): event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item that was deleted.""" type: Literal["conversation.item.deleted"] """The event type, must be `conversation.item.deleted`.""" ================================================ FILE: src/openai/types/beta/realtime/conversation_item_input_audio_transcription_completed_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, TypeAlias from ...._models import BaseModel __all__ = [ "ConversationItemInputAudioTranscriptionCompletedEvent", "Usage", "UsageTranscriptTextUsageTokens", "UsageTranscriptTextUsageTokensInputTokenDetails", "UsageTranscriptTextUsageDuration", "Logprob", ] class UsageTranscriptTextUsageTokensInputTokenDetails(BaseModel): audio_tokens: Optional[int] = None """Number of audio tokens billed for this request.""" text_tokens: Optional[int] = None """Number of text tokens billed for this request.""" class UsageTranscriptTextUsageTokens(BaseModel): input_tokens: int """Number of input tokens billed for this request.""" output_tokens: int """Number of output tokens generated.""" total_tokens: int """Total number of tokens used (input + output).""" type: Literal["tokens"] """The type of the usage object. Always `tokens` for this variant.""" input_token_details: Optional[UsageTranscriptTextUsageTokensInputTokenDetails] = None """Details about the input tokens billed for this request.""" class UsageTranscriptTextUsageDuration(BaseModel): seconds: float """Duration of the input audio in seconds.""" type: Literal["duration"] """The type of the usage object. Always `duration` for this variant.""" Usage: TypeAlias = Union[UsageTranscriptTextUsageTokens, UsageTranscriptTextUsageDuration] class Logprob(BaseModel): token: str """The token that was used to generate the log probability.""" bytes: List[int] """The bytes that were used to generate the log probability.""" logprob: float """The log probability of the token.""" class ConversationItemInputAudioTranscriptionCompletedEvent(BaseModel): content_index: int """The index of the content part containing the audio.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the user message item containing the audio.""" transcript: str """The transcribed text.""" type: Literal["conversation.item.input_audio_transcription.completed"] """ The event type, must be `conversation.item.input_audio_transcription.completed`. """ usage: Usage """Usage statistics for the transcription.""" logprobs: Optional[List[Logprob]] = None """The log probabilities of the transcription.""" ================================================ FILE: src/openai/types/beta/realtime/conversation_item_input_audio_transcription_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ConversationItemInputAudioTranscriptionDeltaEvent", "Logprob"] class Logprob(BaseModel): token: str """The token that was used to generate the log probability.""" bytes: List[int] """The bytes that were used to generate the log probability.""" logprob: float """The log probability of the token.""" class ConversationItemInputAudioTranscriptionDeltaEvent(BaseModel): event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item.""" type: Literal["conversation.item.input_audio_transcription.delta"] """The event type, must be `conversation.item.input_audio_transcription.delta`.""" content_index: Optional[int] = None """The index of the content part in the item's content array.""" delta: Optional[str] = None """The text delta.""" logprobs: Optional[List[Logprob]] = None """The log probabilities of the transcription.""" ================================================ FILE: src/openai/types/beta/realtime/conversation_item_input_audio_transcription_failed_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ConversationItemInputAudioTranscriptionFailedEvent", "Error"] class Error(BaseModel): code: Optional[str] = None """Error code, if any.""" message: Optional[str] = None """A human-readable error message.""" param: Optional[str] = None """Parameter related to the error, if any.""" type: Optional[str] = None """The type of error.""" class ConversationItemInputAudioTranscriptionFailedEvent(BaseModel): content_index: int """The index of the content part containing the audio.""" error: Error """Details of the transcription error.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the user message item.""" type: Literal["conversation.item.input_audio_transcription.failed"] """The event type, must be `conversation.item.input_audio_transcription.failed`.""" ================================================ FILE: src/openai/types/beta/realtime/conversation_item_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Iterable from typing_extensions import Literal, TypedDict from .conversation_item_content_param import ConversationItemContentParam __all__ = ["ConversationItemParam"] class ConversationItemParam(TypedDict, total=False): id: str """ The unique ID of the item, this can be generated by the client to help manage server-side context, but is not required because the server will generate one if not provided. """ arguments: str """The arguments of the function call (for `function_call` items).""" call_id: str """ The ID of the function call (for `function_call` and `function_call_output` items). If passed on a `function_call_output` item, the server will check that a `function_call` item with the same ID exists in the conversation history. """ content: Iterable[ConversationItemContentParam] """The content of the message, applicable for `message` items. - Message items of role `system` support only `input_text` content - Message items of role `user` support `input_text` and `input_audio` content - Message items of role `assistant` support `text` content. """ name: str """The name of the function being called (for `function_call` items).""" object: Literal["realtime.item"] """Identifier for the API object being returned - always `realtime.item`.""" output: str """The output of the function call (for `function_call_output` items).""" role: Literal["user", "assistant", "system"] """ The role of the message sender (`user`, `assistant`, `system`), only applicable for `message` items. """ status: Literal["completed", "incomplete", "in_progress"] """The status of the item (`completed`, `incomplete`, `in_progress`). These have no effect on the conversation, but are accepted for consistency with the `conversation.item.created` event. """ type: Literal["message", "function_call", "function_call_output"] """The type of the item (`message`, `function_call`, `function_call_output`).""" ================================================ FILE: src/openai/types/beta/realtime/conversation_item_retrieve_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ConversationItemRetrieveEvent"] class ConversationItemRetrieveEvent(BaseModel): item_id: str """The ID of the item to retrieve.""" type: Literal["conversation.item.retrieve"] """The event type, must be `conversation.item.retrieve`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/beta/realtime/conversation_item_retrieve_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ConversationItemRetrieveEventParam"] class ConversationItemRetrieveEventParam(TypedDict, total=False): item_id: Required[str] """The ID of the item to retrieve.""" type: Required[Literal["conversation.item.retrieve"]] """The event type, must be `conversation.item.retrieve`.""" event_id: str """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/beta/realtime/conversation_item_truncate_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ConversationItemTruncateEvent"] class ConversationItemTruncateEvent(BaseModel): audio_end_ms: int """Inclusive duration up to which audio is truncated, in milliseconds. If the audio_end_ms is greater than the actual audio duration, the server will respond with an error. """ content_index: int """The index of the content part to truncate. Set this to 0.""" item_id: str """The ID of the assistant message item to truncate. Only assistant message items can be truncated. """ type: Literal["conversation.item.truncate"] """The event type, must be `conversation.item.truncate`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/beta/realtime/conversation_item_truncate_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ConversationItemTruncateEventParam"] class ConversationItemTruncateEventParam(TypedDict, total=False): audio_end_ms: Required[int] """Inclusive duration up to which audio is truncated, in milliseconds. If the audio_end_ms is greater than the actual audio duration, the server will respond with an error. """ content_index: Required[int] """The index of the content part to truncate. Set this to 0.""" item_id: Required[str] """The ID of the assistant message item to truncate. Only assistant message items can be truncated. """ type: Required[Literal["conversation.item.truncate"]] """The event type, must be `conversation.item.truncate`.""" event_id: str """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/beta/realtime/conversation_item_truncated_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ConversationItemTruncatedEvent"] class ConversationItemTruncatedEvent(BaseModel): audio_end_ms: int """The duration up to which the audio was truncated, in milliseconds.""" content_index: int """The index of the content part that was truncated.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the assistant message item that was truncated.""" type: Literal["conversation.item.truncated"] """The event type, must be `conversation.item.truncated`.""" ================================================ FILE: src/openai/types/beta/realtime/conversation_item_with_reference.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ConversationItemWithReference", "Content"] class Content(BaseModel): id: Optional[str] = None """ ID of a previous conversation item to reference (for `item_reference` content types in `response.create` events). These can reference both client and server created items. """ audio: Optional[str] = None """Base64-encoded audio bytes, used for `input_audio` content type.""" text: Optional[str] = None """The text content, used for `input_text` and `text` content types.""" transcript: Optional[str] = None """The transcript of the audio, used for `input_audio` content type.""" type: Optional[Literal["input_text", "input_audio", "item_reference", "text"]] = None """The content type (`input_text`, `input_audio`, `item_reference`, `text`).""" class ConversationItemWithReference(BaseModel): id: Optional[str] = None """ For an item of type (`message` | `function_call` | `function_call_output`) this field allows the client to assign the unique ID of the item. It is not required because the server will generate one if not provided. For an item of type `item_reference`, this field is required and is a reference to any item that has previously existed in the conversation. """ arguments: Optional[str] = None """The arguments of the function call (for `function_call` items).""" call_id: Optional[str] = None """ The ID of the function call (for `function_call` and `function_call_output` items). If passed on a `function_call_output` item, the server will check that a `function_call` item with the same ID exists in the conversation history. """ content: Optional[List[Content]] = None """The content of the message, applicable for `message` items. - Message items of role `system` support only `input_text` content - Message items of role `user` support `input_text` and `input_audio` content - Message items of role `assistant` support `text` content. """ name: Optional[str] = None """The name of the function being called (for `function_call` items).""" object: Optional[Literal["realtime.item"]] = None """Identifier for the API object being returned - always `realtime.item`.""" output: Optional[str] = None """The output of the function call (for `function_call_output` items).""" role: Optional[Literal["user", "assistant", "system"]] = None """ The role of the message sender (`user`, `assistant`, `system`), only applicable for `message` items. """ status: Optional[Literal["completed", "incomplete", "in_progress"]] = None """The status of the item (`completed`, `incomplete`, `in_progress`). These have no effect on the conversation, but are accepted for consistency with the `conversation.item.created` event. """ type: Optional[Literal["message", "function_call", "function_call_output", "item_reference"]] = None """ The type of the item (`message`, `function_call`, `function_call_output`, `item_reference`). """ ================================================ FILE: src/openai/types/beta/realtime/conversation_item_with_reference_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Iterable from typing_extensions import Literal, TypedDict __all__ = ["ConversationItemWithReferenceParam", "Content"] class Content(TypedDict, total=False): id: str """ ID of a previous conversation item to reference (for `item_reference` content types in `response.create` events). These can reference both client and server created items. """ audio: str """Base64-encoded audio bytes, used for `input_audio` content type.""" text: str """The text content, used for `input_text` and `text` content types.""" transcript: str """The transcript of the audio, used for `input_audio` content type.""" type: Literal["input_text", "input_audio", "item_reference", "text"] """The content type (`input_text`, `input_audio`, `item_reference`, `text`).""" class ConversationItemWithReferenceParam(TypedDict, total=False): id: str """ For an item of type (`message` | `function_call` | `function_call_output`) this field allows the client to assign the unique ID of the item. It is not required because the server will generate one if not provided. For an item of type `item_reference`, this field is required and is a reference to any item that has previously existed in the conversation. """ arguments: str """The arguments of the function call (for `function_call` items).""" call_id: str """ The ID of the function call (for `function_call` and `function_call_output` items). If passed on a `function_call_output` item, the server will check that a `function_call` item with the same ID exists in the conversation history. """ content: Iterable[Content] """The content of the message, applicable for `message` items. - Message items of role `system` support only `input_text` content - Message items of role `user` support `input_text` and `input_audio` content - Message items of role `assistant` support `text` content. """ name: str """The name of the function being called (for `function_call` items).""" object: Literal["realtime.item"] """Identifier for the API object being returned - always `realtime.item`.""" output: str """The output of the function call (for `function_call_output` items).""" role: Literal["user", "assistant", "system"] """ The role of the message sender (`user`, `assistant`, `system`), only applicable for `message` items. """ status: Literal["completed", "incomplete", "in_progress"] """The status of the item (`completed`, `incomplete`, `in_progress`). These have no effect on the conversation, but are accepted for consistency with the `conversation.item.created` event. """ type: Literal["message", "function_call", "function_call_output", "item_reference"] """ The type of the item (`message`, `function_call`, `function_call_output`, `item_reference`). """ ================================================ FILE: src/openai/types/beta/realtime/error_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ErrorEvent", "Error"] class Error(BaseModel): message: str """A human-readable error message.""" type: str """The type of error (e.g., "invalid_request_error", "server_error").""" code: Optional[str] = None """Error code, if any.""" event_id: Optional[str] = None """The event_id of the client event that caused the error, if applicable.""" param: Optional[str] = None """Parameter related to the error, if any.""" class ErrorEvent(BaseModel): error: Error """Details of the error.""" event_id: str """The unique ID of the server event.""" type: Literal["error"] """The event type, must be `error`.""" ================================================ FILE: src/openai/types/beta/realtime/input_audio_buffer_append_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["InputAudioBufferAppendEvent"] class InputAudioBufferAppendEvent(BaseModel): audio: str """Base64-encoded audio bytes. This must be in the format specified by the `input_audio_format` field in the session configuration. """ type: Literal["input_audio_buffer.append"] """The event type, must be `input_audio_buffer.append`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/beta/realtime/input_audio_buffer_append_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["InputAudioBufferAppendEventParam"] class InputAudioBufferAppendEventParam(TypedDict, total=False): audio: Required[str] """Base64-encoded audio bytes. This must be in the format specified by the `input_audio_format` field in the session configuration. """ type: Required[Literal["input_audio_buffer.append"]] """The event type, must be `input_audio_buffer.append`.""" event_id: str """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/beta/realtime/input_audio_buffer_clear_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["InputAudioBufferClearEvent"] class InputAudioBufferClearEvent(BaseModel): type: Literal["input_audio_buffer.clear"] """The event type, must be `input_audio_buffer.clear`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/beta/realtime/input_audio_buffer_clear_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["InputAudioBufferClearEventParam"] class InputAudioBufferClearEventParam(TypedDict, total=False): type: Required[Literal["input_audio_buffer.clear"]] """The event type, must be `input_audio_buffer.clear`.""" event_id: str """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/beta/realtime/input_audio_buffer_cleared_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["InputAudioBufferClearedEvent"] class InputAudioBufferClearedEvent(BaseModel): event_id: str """The unique ID of the server event.""" type: Literal["input_audio_buffer.cleared"] """The event type, must be `input_audio_buffer.cleared`.""" ================================================ FILE: src/openai/types/beta/realtime/input_audio_buffer_commit_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["InputAudioBufferCommitEvent"] class InputAudioBufferCommitEvent(BaseModel): type: Literal["input_audio_buffer.commit"] """The event type, must be `input_audio_buffer.commit`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/beta/realtime/input_audio_buffer_commit_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["InputAudioBufferCommitEventParam"] class InputAudioBufferCommitEventParam(TypedDict, total=False): type: Required[Literal["input_audio_buffer.commit"]] """The event type, must be `input_audio_buffer.commit`.""" event_id: str """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/beta/realtime/input_audio_buffer_committed_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["InputAudioBufferCommittedEvent"] class InputAudioBufferCommittedEvent(BaseModel): event_id: str """The unique ID of the server event.""" item_id: str """The ID of the user message item that will be created.""" type: Literal["input_audio_buffer.committed"] """The event type, must be `input_audio_buffer.committed`.""" previous_item_id: Optional[str] = None """ The ID of the preceding item after which the new item will be inserted. Can be `null` if the item has no predecessor. """ ================================================ FILE: src/openai/types/beta/realtime/input_audio_buffer_speech_started_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["InputAudioBufferSpeechStartedEvent"] class InputAudioBufferSpeechStartedEvent(BaseModel): audio_start_ms: int """ Milliseconds from the start of all audio written to the buffer during the session when speech was first detected. This will correspond to the beginning of audio sent to the model, and thus includes the `prefix_padding_ms` configured in the Session. """ event_id: str """The unique ID of the server event.""" item_id: str """The ID of the user message item that will be created when speech stops.""" type: Literal["input_audio_buffer.speech_started"] """The event type, must be `input_audio_buffer.speech_started`.""" ================================================ FILE: src/openai/types/beta/realtime/input_audio_buffer_speech_stopped_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["InputAudioBufferSpeechStoppedEvent"] class InputAudioBufferSpeechStoppedEvent(BaseModel): audio_end_ms: int """Milliseconds since the session started when speech stopped. This will correspond to the end of audio sent to the model, and thus includes the `min_silence_duration_ms` configured in the Session. """ event_id: str """The unique ID of the server event.""" item_id: str """The ID of the user message item that will be created.""" type: Literal["input_audio_buffer.speech_stopped"] """The event type, must be `input_audio_buffer.speech_stopped`.""" ================================================ FILE: src/openai/types/beta/realtime/rate_limits_updated_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["RateLimitsUpdatedEvent", "RateLimit"] class RateLimit(BaseModel): limit: Optional[int] = None """The maximum allowed value for the rate limit.""" name: Optional[Literal["requests", "tokens"]] = None """The name of the rate limit (`requests`, `tokens`).""" remaining: Optional[int] = None """The remaining value before the limit is reached.""" reset_seconds: Optional[float] = None """Seconds until the rate limit resets.""" class RateLimitsUpdatedEvent(BaseModel): event_id: str """The unique ID of the server event.""" rate_limits: List[RateLimit] """List of rate limit information.""" type: Literal["rate_limits.updated"] """The event type, must be `rate_limits.updated`.""" ================================================ FILE: src/openai/types/beta/realtime/realtime_client_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ...._utils import PropertyInfo from ...._models import BaseModel from .session_update_event import SessionUpdateEvent from .response_cancel_event import ResponseCancelEvent from .response_create_event import ResponseCreateEvent from .transcription_session_update import TranscriptionSessionUpdate from .conversation_item_create_event import ConversationItemCreateEvent from .conversation_item_delete_event import ConversationItemDeleteEvent from .input_audio_buffer_clear_event import InputAudioBufferClearEvent from .input_audio_buffer_append_event import InputAudioBufferAppendEvent from .input_audio_buffer_commit_event import InputAudioBufferCommitEvent from .conversation_item_retrieve_event import ConversationItemRetrieveEvent from .conversation_item_truncate_event import ConversationItemTruncateEvent __all__ = ["RealtimeClientEvent", "OutputAudioBufferClear"] class OutputAudioBufferClear(BaseModel): type: Literal["output_audio_buffer.clear"] """The event type, must be `output_audio_buffer.clear`.""" event_id: Optional[str] = None """The unique ID of the client event used for error handling.""" RealtimeClientEvent: TypeAlias = Annotated[ Union[ ConversationItemCreateEvent, ConversationItemDeleteEvent, ConversationItemRetrieveEvent, ConversationItemTruncateEvent, InputAudioBufferAppendEvent, InputAudioBufferClearEvent, OutputAudioBufferClear, InputAudioBufferCommitEvent, ResponseCancelEvent, ResponseCreateEvent, SessionUpdateEvent, TranscriptionSessionUpdate, ], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/types/beta/realtime/realtime_client_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, Required, TypeAlias, TypedDict from .session_update_event_param import SessionUpdateEventParam from .response_cancel_event_param import ResponseCancelEventParam from .response_create_event_param import ResponseCreateEventParam from .transcription_session_update_param import TranscriptionSessionUpdateParam from .conversation_item_create_event_param import ConversationItemCreateEventParam from .conversation_item_delete_event_param import ConversationItemDeleteEventParam from .input_audio_buffer_clear_event_param import InputAudioBufferClearEventParam from .input_audio_buffer_append_event_param import InputAudioBufferAppendEventParam from .input_audio_buffer_commit_event_param import InputAudioBufferCommitEventParam from .conversation_item_retrieve_event_param import ConversationItemRetrieveEventParam from .conversation_item_truncate_event_param import ConversationItemTruncateEventParam __all__ = ["RealtimeClientEventParam", "OutputAudioBufferClear"] class OutputAudioBufferClear(TypedDict, total=False): type: Required[Literal["output_audio_buffer.clear"]] """The event type, must be `output_audio_buffer.clear`.""" event_id: str """The unique ID of the client event used for error handling.""" RealtimeClientEventParam: TypeAlias = Union[ ConversationItemCreateEventParam, ConversationItemDeleteEventParam, ConversationItemRetrieveEventParam, ConversationItemTruncateEventParam, InputAudioBufferAppendEventParam, InputAudioBufferClearEventParam, OutputAudioBufferClear, InputAudioBufferCommitEventParam, ResponseCancelEventParam, ResponseCreateEventParam, SessionUpdateEventParam, TranscriptionSessionUpdateParam, ] ================================================ FILE: src/openai/types/beta/realtime/realtime_connect_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Required, TypedDict __all__ = ["RealtimeConnectParams"] class RealtimeConnectParams(TypedDict, total=False): model: Required[str] ================================================ FILE: src/openai/types/beta/realtime/realtime_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal from ...._models import BaseModel from ...shared.metadata import Metadata from .conversation_item import ConversationItem from .realtime_response_usage import RealtimeResponseUsage from .realtime_response_status import RealtimeResponseStatus __all__ = ["RealtimeResponse"] class RealtimeResponse(BaseModel): id: Optional[str] = None """The unique ID of the response.""" conversation_id: Optional[str] = None """ Which conversation the response is added to, determined by the `conversation` field in the `response.create` event. If `auto`, the response will be added to the default conversation and the value of `conversation_id` will be an id like `conv_1234`. If `none`, the response will not be added to any conversation and the value of `conversation_id` will be `null`. If responses are being triggered by server VAD, the response will be added to the default conversation, thus the `conversation_id` will be an id like `conv_1234`. """ max_output_tokens: Union[int, Literal["inf"], None] = None """ Maximum number of output tokens for a single assistant response, inclusive of tool calls, that was used in this response. """ metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ modalities: Optional[List[Literal["text", "audio"]]] = None """The set of modalities the model used to respond. If there are multiple modalities, the model will pick one, for example if `modalities` is `["text", "audio"]`, the model could be responding in either text or audio. """ object: Optional[Literal["realtime.response"]] = None """The object type, must be `realtime.response`.""" output: Optional[List[ConversationItem]] = None """The list of output items generated by the response.""" output_audio_format: Optional[Literal["pcm16", "g711_ulaw", "g711_alaw"]] = None """The format of output audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`.""" status: Optional[Literal["completed", "cancelled", "failed", "incomplete", "in_progress"]] = None """ The final status of the response (`completed`, `cancelled`, `failed`, or `incomplete`, `in_progress`). """ status_details: Optional[RealtimeResponseStatus] = None """Additional details about the status.""" temperature: Optional[float] = None """Sampling temperature for the model, limited to [0.6, 1.2]. Defaults to 0.8.""" usage: Optional[RealtimeResponseUsage] = None """Usage statistics for the Response, this will correspond to billing. A Realtime API session will maintain a conversation context and append new Items to the Conversation, thus output from previous turns (text and audio tokens) will become the input for later turns. """ voice: Union[str, Literal["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse"], None] = None """ The voice the model used to respond. Current voice options are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, and `verse`. """ ================================================ FILE: src/openai/types/beta/realtime/realtime_response_status.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["RealtimeResponseStatus", "Error"] class Error(BaseModel): code: Optional[str] = None """Error code, if any.""" type: Optional[str] = None """The type of error.""" class RealtimeResponseStatus(BaseModel): error: Optional[Error] = None """ A description of the error that caused the response to fail, populated when the `status` is `failed`. """ reason: Optional[Literal["turn_detected", "client_cancelled", "max_output_tokens", "content_filter"]] = None """The reason the Response did not complete. For a `cancelled` Response, one of `turn_detected` (the server VAD detected a new start of speech) or `client_cancelled` (the client sent a cancel event). For an `incomplete` Response, one of `max_output_tokens` or `content_filter` (the server-side safety filter activated and cut off the response). """ type: Optional[Literal["completed", "cancelled", "incomplete", "failed"]] = None """ The type of error that caused the response to fail, corresponding with the `status` field (`completed`, `cancelled`, `incomplete`, `failed`). """ ================================================ FILE: src/openai/types/beta/realtime/realtime_response_usage.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from ...._models import BaseModel __all__ = ["RealtimeResponseUsage", "InputTokenDetails", "OutputTokenDetails"] class InputTokenDetails(BaseModel): audio_tokens: Optional[int] = None """The number of audio tokens used in the Response.""" cached_tokens: Optional[int] = None """The number of cached tokens used in the Response.""" text_tokens: Optional[int] = None """The number of text tokens used in the Response.""" class OutputTokenDetails(BaseModel): audio_tokens: Optional[int] = None """The number of audio tokens used in the Response.""" text_tokens: Optional[int] = None """The number of text tokens used in the Response.""" class RealtimeResponseUsage(BaseModel): input_token_details: Optional[InputTokenDetails] = None """Details about the input tokens used in the Response.""" input_tokens: Optional[int] = None """ The number of input tokens used in the Response, including text and audio tokens. """ output_token_details: Optional[OutputTokenDetails] = None """Details about the output tokens used in the Response.""" output_tokens: Optional[int] = None """ The number of output tokens sent in the Response, including text and audio tokens. """ total_tokens: Optional[int] = None """ The total number of tokens in the Response including input and output text and audio tokens. """ ================================================ FILE: src/openai/types/beta/realtime/realtime_server_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Literal, Annotated, TypeAlias from ...._utils import PropertyInfo from ...._models import BaseModel from .error_event import ErrorEvent from .conversation_item import ConversationItem from .response_done_event import ResponseDoneEvent from .session_created_event import SessionCreatedEvent from .session_updated_event import SessionUpdatedEvent from .response_created_event import ResponseCreatedEvent from .response_text_done_event import ResponseTextDoneEvent from .rate_limits_updated_event import RateLimitsUpdatedEvent from .response_audio_done_event import ResponseAudioDoneEvent from .response_text_delta_event import ResponseTextDeltaEvent from .conversation_created_event import ConversationCreatedEvent from .response_audio_delta_event import ResponseAudioDeltaEvent from .conversation_item_created_event import ConversationItemCreatedEvent from .conversation_item_deleted_event import ConversationItemDeletedEvent from .response_output_item_done_event import ResponseOutputItemDoneEvent from .input_audio_buffer_cleared_event import InputAudioBufferClearedEvent from .response_content_part_done_event import ResponseContentPartDoneEvent from .response_output_item_added_event import ResponseOutputItemAddedEvent from .conversation_item_truncated_event import ConversationItemTruncatedEvent from .response_content_part_added_event import ResponseContentPartAddedEvent from .input_audio_buffer_committed_event import InputAudioBufferCommittedEvent from .transcription_session_updated_event import TranscriptionSessionUpdatedEvent from .response_audio_transcript_done_event import ResponseAudioTranscriptDoneEvent from .response_audio_transcript_delta_event import ResponseAudioTranscriptDeltaEvent from .input_audio_buffer_speech_started_event import InputAudioBufferSpeechStartedEvent from .input_audio_buffer_speech_stopped_event import InputAudioBufferSpeechStoppedEvent from .response_function_call_arguments_done_event import ResponseFunctionCallArgumentsDoneEvent from .response_function_call_arguments_delta_event import ResponseFunctionCallArgumentsDeltaEvent from .conversation_item_input_audio_transcription_delta_event import ConversationItemInputAudioTranscriptionDeltaEvent from .conversation_item_input_audio_transcription_failed_event import ConversationItemInputAudioTranscriptionFailedEvent from .conversation_item_input_audio_transcription_completed_event import ( ConversationItemInputAudioTranscriptionCompletedEvent, ) __all__ = [ "RealtimeServerEvent", "ConversationItemRetrieved", "OutputAudioBufferStarted", "OutputAudioBufferStopped", "OutputAudioBufferCleared", ] class ConversationItemRetrieved(BaseModel): event_id: str """The unique ID of the server event.""" item: ConversationItem """The item to add to the conversation.""" type: Literal["conversation.item.retrieved"] """The event type, must be `conversation.item.retrieved`.""" class OutputAudioBufferStarted(BaseModel): event_id: str """The unique ID of the server event.""" response_id: str """The unique ID of the response that produced the audio.""" type: Literal["output_audio_buffer.started"] """The event type, must be `output_audio_buffer.started`.""" class OutputAudioBufferStopped(BaseModel): event_id: str """The unique ID of the server event.""" response_id: str """The unique ID of the response that produced the audio.""" type: Literal["output_audio_buffer.stopped"] """The event type, must be `output_audio_buffer.stopped`.""" class OutputAudioBufferCleared(BaseModel): event_id: str """The unique ID of the server event.""" response_id: str """The unique ID of the response that produced the audio.""" type: Literal["output_audio_buffer.cleared"] """The event type, must be `output_audio_buffer.cleared`.""" RealtimeServerEvent: TypeAlias = Annotated[ Union[ ConversationCreatedEvent, ConversationItemCreatedEvent, ConversationItemDeletedEvent, ConversationItemInputAudioTranscriptionCompletedEvent, ConversationItemInputAudioTranscriptionDeltaEvent, ConversationItemInputAudioTranscriptionFailedEvent, ConversationItemRetrieved, ConversationItemTruncatedEvent, ErrorEvent, InputAudioBufferClearedEvent, InputAudioBufferCommittedEvent, InputAudioBufferSpeechStartedEvent, InputAudioBufferSpeechStoppedEvent, RateLimitsUpdatedEvent, ResponseAudioDeltaEvent, ResponseAudioDoneEvent, ResponseAudioTranscriptDeltaEvent, ResponseAudioTranscriptDoneEvent, ResponseContentPartAddedEvent, ResponseContentPartDoneEvent, ResponseCreatedEvent, ResponseDoneEvent, ResponseFunctionCallArgumentsDeltaEvent, ResponseFunctionCallArgumentsDoneEvent, ResponseOutputItemAddedEvent, ResponseOutputItemDoneEvent, ResponseTextDeltaEvent, ResponseTextDoneEvent, SessionCreatedEvent, SessionUpdatedEvent, TranscriptionSessionUpdatedEvent, OutputAudioBufferStarted, OutputAudioBufferStopped, OutputAudioBufferCleared, ], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/types/beta/realtime/response_audio_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ResponseAudioDeltaEvent"] class ResponseAudioDeltaEvent(BaseModel): content_index: int """The index of the content part in the item's content array.""" delta: str """Base64-encoded audio data delta.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item.""" output_index: int """The index of the output item in the response.""" response_id: str """The ID of the response.""" type: Literal["response.audio.delta"] """The event type, must be `response.audio.delta`.""" ================================================ FILE: src/openai/types/beta/realtime/response_audio_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ResponseAudioDoneEvent"] class ResponseAudioDoneEvent(BaseModel): content_index: int """The index of the content part in the item's content array.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item.""" output_index: int """The index of the output item in the response.""" response_id: str """The ID of the response.""" type: Literal["response.audio.done"] """The event type, must be `response.audio.done`.""" ================================================ FILE: src/openai/types/beta/realtime/response_audio_transcript_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ResponseAudioTranscriptDeltaEvent"] class ResponseAudioTranscriptDeltaEvent(BaseModel): content_index: int """The index of the content part in the item's content array.""" delta: str """The transcript delta.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item.""" output_index: int """The index of the output item in the response.""" response_id: str """The ID of the response.""" type: Literal["response.audio_transcript.delta"] """The event type, must be `response.audio_transcript.delta`.""" ================================================ FILE: src/openai/types/beta/realtime/response_audio_transcript_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ResponseAudioTranscriptDoneEvent"] class ResponseAudioTranscriptDoneEvent(BaseModel): content_index: int """The index of the content part in the item's content array.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item.""" output_index: int """The index of the output item in the response.""" response_id: str """The ID of the response.""" transcript: str """The final transcript of the audio.""" type: Literal["response.audio_transcript.done"] """The event type, must be `response.audio_transcript.done`.""" ================================================ FILE: src/openai/types/beta/realtime/response_cancel_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ResponseCancelEvent"] class ResponseCancelEvent(BaseModel): type: Literal["response.cancel"] """The event type, must be `response.cancel`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" response_id: Optional[str] = None """ A specific response ID to cancel - if not provided, will cancel an in-progress response in the default conversation. """ ================================================ FILE: src/openai/types/beta/realtime/response_cancel_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ResponseCancelEventParam"] class ResponseCancelEventParam(TypedDict, total=False): type: Required[Literal["response.cancel"]] """The event type, must be `response.cancel`.""" event_id: str """Optional client-generated ID used to identify this event.""" response_id: str """ A specific response ID to cancel - if not provided, will cancel an in-progress response in the default conversation. """ ================================================ FILE: src/openai/types/beta/realtime/response_content_part_added_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ResponseContentPartAddedEvent", "Part"] class Part(BaseModel): audio: Optional[str] = None """Base64-encoded audio data (if type is "audio").""" text: Optional[str] = None """The text content (if type is "text").""" transcript: Optional[str] = None """The transcript of the audio (if type is "audio").""" type: Optional[Literal["text", "audio"]] = None """The content type ("text", "audio").""" class ResponseContentPartAddedEvent(BaseModel): content_index: int """The index of the content part in the item's content array.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item to which the content part was added.""" output_index: int """The index of the output item in the response.""" part: Part """The content part that was added.""" response_id: str """The ID of the response.""" type: Literal["response.content_part.added"] """The event type, must be `response.content_part.added`.""" ================================================ FILE: src/openai/types/beta/realtime/response_content_part_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ResponseContentPartDoneEvent", "Part"] class Part(BaseModel): audio: Optional[str] = None """Base64-encoded audio data (if type is "audio").""" text: Optional[str] = None """The text content (if type is "text").""" transcript: Optional[str] = None """The transcript of the audio (if type is "audio").""" type: Optional[Literal["text", "audio"]] = None """The content type ("text", "audio").""" class ResponseContentPartDoneEvent(BaseModel): content_index: int """The index of the content part in the item's content array.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item.""" output_index: int """The index of the output item in the response.""" part: Part """The content part that is done.""" response_id: str """The ID of the response.""" type: Literal["response.content_part.done"] """The event type, must be `response.content_part.done`.""" ================================================ FILE: src/openai/types/beta/realtime/response_create_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal from ...._models import BaseModel from ...shared.metadata import Metadata from .conversation_item_with_reference import ConversationItemWithReference __all__ = ["ResponseCreateEvent", "Response", "ResponseTool"] class ResponseTool(BaseModel): description: Optional[str] = None """ The description of the function, including guidance on when and how to call it, and guidance about what to tell the user when calling (if anything). """ name: Optional[str] = None """The name of the function.""" parameters: Optional[object] = None """Parameters of the function in JSON Schema.""" type: Optional[Literal["function"]] = None """The type of the tool, i.e. `function`.""" class Response(BaseModel): conversation: Union[str, Literal["auto", "none"], None] = None """Controls which conversation the response is added to. Currently supports `auto` and `none`, with `auto` as the default value. The `auto` value means that the contents of the response will be added to the default conversation. Set this to `none` to create an out-of-band response which will not add items to default conversation. """ input: Optional[List[ConversationItemWithReference]] = None """Input items to include in the prompt for the model. Using this field creates a new context for this Response instead of using the default conversation. An empty array `[]` will clear the context for this Response. Note that this can include references to items from the default conversation. """ instructions: Optional[str] = None """The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. "be extremely succinct", "act friendly", "here are examples of good responses") and on audio behavior (e.g. "talk quickly", "inject emotion into your voice", "laugh frequently"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior. Note that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session. """ max_response_output_tokens: Union[int, Literal["inf"], None] = None """ Maximum number of output tokens for a single assistant response, inclusive of tool calls. Provide an integer between 1 and 4096 to limit output tokens, or `inf` for the maximum available tokens for a given model. Defaults to `inf`. """ metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ modalities: Optional[List[Literal["text", "audio"]]] = None """The set of modalities the model can respond with. To disable audio, set this to ["text"]. """ output_audio_format: Optional[Literal["pcm16", "g711_ulaw", "g711_alaw"]] = None """The format of output audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`.""" temperature: Optional[float] = None """Sampling temperature for the model, limited to [0.6, 1.2]. Defaults to 0.8.""" tool_choice: Optional[str] = None """How the model chooses tools. Options are `auto`, `none`, `required`, or specify a function, like `{"type": "function", "function": {"name": "my_function"}}`. """ tools: Optional[List[ResponseTool]] = None """Tools (functions) available to the model.""" voice: Union[str, Literal["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse"], None] = None """The voice the model uses to respond. Voice cannot be changed during the session once the model has responded with audio at least once. Current voice options are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, and `verse`. """ class ResponseCreateEvent(BaseModel): type: Literal["response.create"] """The event type, must be `response.create`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" response: Optional[Response] = None """Create a new Realtime response with these parameters""" ================================================ FILE: src/openai/types/beta/realtime/response_create_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List, Union, Iterable, Optional from typing_extensions import Literal, Required, TypedDict from ...shared_params.metadata import Metadata from .conversation_item_with_reference_param import ConversationItemWithReferenceParam __all__ = ["ResponseCreateEventParam", "Response", "ResponseTool"] class ResponseTool(TypedDict, total=False): description: str """ The description of the function, including guidance on when and how to call it, and guidance about what to tell the user when calling (if anything). """ name: str """The name of the function.""" parameters: object """Parameters of the function in JSON Schema.""" type: Literal["function"] """The type of the tool, i.e. `function`.""" class Response(TypedDict, total=False): conversation: Union[str, Literal["auto", "none"]] """Controls which conversation the response is added to. Currently supports `auto` and `none`, with `auto` as the default value. The `auto` value means that the contents of the response will be added to the default conversation. Set this to `none` to create an out-of-band response which will not add items to default conversation. """ input: Iterable[ConversationItemWithReferenceParam] """Input items to include in the prompt for the model. Using this field creates a new context for this Response instead of using the default conversation. An empty array `[]` will clear the context for this Response. Note that this can include references to items from the default conversation. """ instructions: str """The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. "be extremely succinct", "act friendly", "here are examples of good responses") and on audio behavior (e.g. "talk quickly", "inject emotion into your voice", "laugh frequently"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior. Note that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session. """ max_response_output_tokens: Union[int, Literal["inf"]] """ Maximum number of output tokens for a single assistant response, inclusive of tool calls. Provide an integer between 1 and 4096 to limit output tokens, or `inf` for the maximum available tokens for a given model. Defaults to `inf`. """ metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ modalities: List[Literal["text", "audio"]] """The set of modalities the model can respond with. To disable audio, set this to ["text"]. """ output_audio_format: Literal["pcm16", "g711_ulaw", "g711_alaw"] """The format of output audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`.""" temperature: float """Sampling temperature for the model, limited to [0.6, 1.2]. Defaults to 0.8.""" tool_choice: str """How the model chooses tools. Options are `auto`, `none`, `required`, or specify a function, like `{"type": "function", "function": {"name": "my_function"}}`. """ tools: Iterable[ResponseTool] """Tools (functions) available to the model.""" voice: Union[str, Literal["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse"]] """The voice the model uses to respond. Voice cannot be changed during the session once the model has responded with audio at least once. Current voice options are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, and `verse`. """ class ResponseCreateEventParam(TypedDict, total=False): type: Required[Literal["response.create"]] """The event type, must be `response.create`.""" event_id: str """Optional client-generated ID used to identify this event.""" response: Response """Create a new Realtime response with these parameters""" ================================================ FILE: src/openai/types/beta/realtime/response_created_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel from .realtime_response import RealtimeResponse __all__ = ["ResponseCreatedEvent"] class ResponseCreatedEvent(BaseModel): event_id: str """The unique ID of the server event.""" response: RealtimeResponse """The response resource.""" type: Literal["response.created"] """The event type, must be `response.created`.""" ================================================ FILE: src/openai/types/beta/realtime/response_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel from .realtime_response import RealtimeResponse __all__ = ["ResponseDoneEvent"] class ResponseDoneEvent(BaseModel): event_id: str """The unique ID of the server event.""" response: RealtimeResponse """The response resource.""" type: Literal["response.done"] """The event type, must be `response.done`.""" ================================================ FILE: src/openai/types/beta/realtime/response_function_call_arguments_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ResponseFunctionCallArgumentsDeltaEvent"] class ResponseFunctionCallArgumentsDeltaEvent(BaseModel): call_id: str """The ID of the function call.""" delta: str """The arguments delta as a JSON string.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the function call item.""" output_index: int """The index of the output item in the response.""" response_id: str """The ID of the response.""" type: Literal["response.function_call_arguments.delta"] """The event type, must be `response.function_call_arguments.delta`.""" ================================================ FILE: src/openai/types/beta/realtime/response_function_call_arguments_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ResponseFunctionCallArgumentsDoneEvent"] class ResponseFunctionCallArgumentsDoneEvent(BaseModel): arguments: str """The final arguments as a JSON string.""" call_id: str """The ID of the function call.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the function call item.""" output_index: int """The index of the output item in the response.""" response_id: str """The ID of the response.""" type: Literal["response.function_call_arguments.done"] """The event type, must be `response.function_call_arguments.done`.""" ================================================ FILE: src/openai/types/beta/realtime/response_output_item_added_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel from .conversation_item import ConversationItem __all__ = ["ResponseOutputItemAddedEvent"] class ResponseOutputItemAddedEvent(BaseModel): event_id: str """The unique ID of the server event.""" item: ConversationItem """The item to add to the conversation.""" output_index: int """The index of the output item in the Response.""" response_id: str """The ID of the Response to which the item belongs.""" type: Literal["response.output_item.added"] """The event type, must be `response.output_item.added`.""" ================================================ FILE: src/openai/types/beta/realtime/response_output_item_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel from .conversation_item import ConversationItem __all__ = ["ResponseOutputItemDoneEvent"] class ResponseOutputItemDoneEvent(BaseModel): event_id: str """The unique ID of the server event.""" item: ConversationItem """The item to add to the conversation.""" output_index: int """The index of the output item in the Response.""" response_id: str """The ID of the Response to which the item belongs.""" type: Literal["response.output_item.done"] """The event type, must be `response.output_item.done`.""" ================================================ FILE: src/openai/types/beta/realtime/response_text_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ResponseTextDeltaEvent"] class ResponseTextDeltaEvent(BaseModel): content_index: int """The index of the content part in the item's content array.""" delta: str """The text delta.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item.""" output_index: int """The index of the output item in the response.""" response_id: str """The ID of the response.""" type: Literal["response.text.delta"] """The event type, must be `response.text.delta`.""" ================================================ FILE: src/openai/types/beta/realtime/response_text_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ResponseTextDoneEvent"] class ResponseTextDoneEvent(BaseModel): content_index: int """The index of the content part in the item's content array.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item.""" output_index: int """The index of the output item in the response.""" response_id: str """The ID of the response.""" text: str """The final text content.""" type: Literal["response.text.done"] """The event type, must be `response.text.done`.""" ================================================ FILE: src/openai/types/beta/realtime/session.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, TypeAlias from ...._models import BaseModel __all__ = [ "Session", "InputAudioNoiseReduction", "InputAudioTranscription", "Tool", "Tracing", "TracingTracingConfiguration", "TurnDetection", ] class InputAudioNoiseReduction(BaseModel): type: Optional[Literal["near_field", "far_field"]] = None """Type of noise reduction. `near_field` is for close-talking microphones such as headphones, `far_field` is for far-field microphones such as laptop or conference room microphones. """ class InputAudioTranscription(BaseModel): language: Optional[str] = None """The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format will improve accuracy and latency. """ model: Optional[str] = None """ The model to use for transcription, current options are `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, and `whisper-1`. """ prompt: Optional[str] = None """ An optional text to guide the model's style or continue a previous audio segment. For `whisper-1`, the [prompt is a list of keywords](https://platform.openai.com/docs/guides/speech-to-text#prompting). For `gpt-4o-transcribe` models, the prompt is a free text string, for example "expect words related to technology". """ class Tool(BaseModel): description: Optional[str] = None """ The description of the function, including guidance on when and how to call it, and guidance about what to tell the user when calling (if anything). """ name: Optional[str] = None """The name of the function.""" parameters: Optional[object] = None """Parameters of the function in JSON Schema.""" type: Optional[Literal["function"]] = None """The type of the tool, i.e. `function`.""" class TracingTracingConfiguration(BaseModel): group_id: Optional[str] = None """ The group id to attach to this trace to enable filtering and grouping in the traces dashboard. """ metadata: Optional[object] = None """ The arbitrary metadata to attach to this trace to enable filtering in the traces dashboard. """ workflow_name: Optional[str] = None """The name of the workflow to attach to this trace. This is used to name the trace in the traces dashboard. """ Tracing: TypeAlias = Union[Literal["auto"], TracingTracingConfiguration] class TurnDetection(BaseModel): create_response: Optional[bool] = None """ Whether or not to automatically generate a response when a VAD stop event occurs. """ eagerness: Optional[Literal["low", "medium", "high", "auto"]] = None """Used only for `semantic_vad` mode. The eagerness of the model to respond. `low` will wait longer for the user to continue speaking, `high` will respond more quickly. `auto` is the default and is equivalent to `medium`. """ interrupt_response: Optional[bool] = None """ Whether or not to automatically interrupt any ongoing response with output to the default conversation (i.e. `conversation` of `auto`) when a VAD start event occurs. """ prefix_padding_ms: Optional[int] = None """Used only for `server_vad` mode. Amount of audio to include before the VAD detected speech (in milliseconds). Defaults to 300ms. """ silence_duration_ms: Optional[int] = None """Used only for `server_vad` mode. Duration of silence to detect speech stop (in milliseconds). Defaults to 500ms. With shorter values the model will respond more quickly, but may jump in on short pauses from the user. """ threshold: Optional[float] = None """Used only for `server_vad` mode. Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A higher threshold will require louder audio to activate the model, and thus might perform better in noisy environments. """ type: Optional[Literal["server_vad", "semantic_vad"]] = None """Type of turn detection.""" class Session(BaseModel): id: Optional[str] = None """Unique identifier for the session that looks like `sess_1234567890abcdef`.""" input_audio_format: Optional[Literal["pcm16", "g711_ulaw", "g711_alaw"]] = None """The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`. For `pcm16`, input audio must be 16-bit PCM at a 24kHz sample rate, single channel (mono), and little-endian byte order. """ input_audio_noise_reduction: Optional[InputAudioNoiseReduction] = None """Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. """ input_audio_transcription: Optional[InputAudioTranscription] = None """ Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](https://platform.openai.com/docs/api-reference/audio/createTranscription) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service. """ instructions: Optional[str] = None """The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. "be extremely succinct", "act friendly", "here are examples of good responses") and on audio behavior (e.g. "talk quickly", "inject emotion into your voice", "laugh frequently"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior. Note that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session. """ max_response_output_tokens: Union[int, Literal["inf"], None] = None """ Maximum number of output tokens for a single assistant response, inclusive of tool calls. Provide an integer between 1 and 4096 to limit output tokens, or `inf` for the maximum available tokens for a given model. Defaults to `inf`. """ modalities: Optional[List[Literal["text", "audio"]]] = None """The set of modalities the model can respond with. To disable audio, set this to ["text"]. """ model: Optional[ Literal[ "gpt-realtime", "gpt-realtime-2025-08-28", "gpt-4o-realtime-preview", "gpt-4o-realtime-preview-2024-10-01", "gpt-4o-realtime-preview-2024-12-17", "gpt-4o-realtime-preview-2025-06-03", "gpt-4o-mini-realtime-preview", "gpt-4o-mini-realtime-preview-2024-12-17", ] ] = None """The Realtime model used for this session.""" output_audio_format: Optional[Literal["pcm16", "g711_ulaw", "g711_alaw"]] = None """The format of output audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`. For `pcm16`, output audio is sampled at a rate of 24kHz. """ speed: Optional[float] = None """The speed of the model's spoken response. 1.0 is the default speed. 0.25 is the minimum speed. 1.5 is the maximum speed. This value can only be changed in between model turns, not while a response is in progress. """ temperature: Optional[float] = None """Sampling temperature for the model, limited to [0.6, 1.2]. For audio models a temperature of 0.8 is highly recommended for best performance. """ tool_choice: Optional[str] = None """How the model chooses tools. Options are `auto`, `none`, `required`, or specify a function. """ tools: Optional[List[Tool]] = None """Tools (functions) available to the model.""" tracing: Optional[Tracing] = None """Configuration options for tracing. Set to null to disable tracing. Once tracing is enabled for a session, the configuration cannot be modified. `auto` will create a trace for the session with default values for the workflow name, group id, and metadata. """ turn_detection: Optional[TurnDetection] = None """Configuration for turn detection, ether Server VAD or Semantic VAD. This can be set to `null` to turn off, in which case the client must manually trigger model response. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. Semantic VAD is more advanced and uses a turn detection model (in conjunction with VAD) to semantically estimate whether the user has finished speaking, then dynamically sets a timeout based on this probability. For example, if user audio trails off with "uhhm", the model will score a low probability of turn end and wait longer for the user to continue speaking. This can be useful for more natural conversations, but may have a higher latency. """ voice: Union[str, Literal["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse"], None] = None """The voice the model uses to respond. Voice cannot be changed during the session once the model has responded with audio at least once. Current voice options are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, and `verse`. """ ================================================ FILE: src/openai/types/beta/realtime/session_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List, Union, Iterable from typing_extensions import Literal, Required, TypeAlias, TypedDict __all__ = [ "SessionCreateParams", "ClientSecret", "ClientSecretExpiresAfter", "InputAudioNoiseReduction", "InputAudioTranscription", "Tool", "Tracing", "TracingTracingConfiguration", "TurnDetection", ] class SessionCreateParams(TypedDict, total=False): client_secret: ClientSecret """Configuration options for the generated client secret.""" input_audio_format: Literal["pcm16", "g711_ulaw", "g711_alaw"] """The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`. For `pcm16`, input audio must be 16-bit PCM at a 24kHz sample rate, single channel (mono), and little-endian byte order. """ input_audio_noise_reduction: InputAudioNoiseReduction """Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. """ input_audio_transcription: InputAudioTranscription """ Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](https://platform.openai.com/docs/api-reference/audio/createTranscription) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service. """ instructions: str """The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. "be extremely succinct", "act friendly", "here are examples of good responses") and on audio behavior (e.g. "talk quickly", "inject emotion into your voice", "laugh frequently"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior. Note that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session. """ max_response_output_tokens: Union[int, Literal["inf"]] """ Maximum number of output tokens for a single assistant response, inclusive of tool calls. Provide an integer between 1 and 4096 to limit output tokens, or `inf` for the maximum available tokens for a given model. Defaults to `inf`. """ modalities: List[Literal["text", "audio"]] """The set of modalities the model can respond with. To disable audio, set this to ["text"]. """ model: Literal[ "gpt-realtime", "gpt-realtime-2025-08-28", "gpt-4o-realtime-preview", "gpt-4o-realtime-preview-2024-10-01", "gpt-4o-realtime-preview-2024-12-17", "gpt-4o-realtime-preview-2025-06-03", "gpt-4o-mini-realtime-preview", "gpt-4o-mini-realtime-preview-2024-12-17", ] """The Realtime model used for this session.""" output_audio_format: Literal["pcm16", "g711_ulaw", "g711_alaw"] """The format of output audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`. For `pcm16`, output audio is sampled at a rate of 24kHz. """ speed: float """The speed of the model's spoken response. 1.0 is the default speed. 0.25 is the minimum speed. 1.5 is the maximum speed. This value can only be changed in between model turns, not while a response is in progress. """ temperature: float """Sampling temperature for the model, limited to [0.6, 1.2]. For audio models a temperature of 0.8 is highly recommended for best performance. """ tool_choice: str """How the model chooses tools. Options are `auto`, `none`, `required`, or specify a function. """ tools: Iterable[Tool] """Tools (functions) available to the model.""" tracing: Tracing """Configuration options for tracing. Set to null to disable tracing. Once tracing is enabled for a session, the configuration cannot be modified. `auto` will create a trace for the session with default values for the workflow name, group id, and metadata. """ turn_detection: TurnDetection """Configuration for turn detection, ether Server VAD or Semantic VAD. This can be set to `null` to turn off, in which case the client must manually trigger model response. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. Semantic VAD is more advanced and uses a turn detection model (in conjunction with VAD) to semantically estimate whether the user has finished speaking, then dynamically sets a timeout based on this probability. For example, if user audio trails off with "uhhm", the model will score a low probability of turn end and wait longer for the user to continue speaking. This can be useful for more natural conversations, but may have a higher latency. """ voice: Union[str, Literal["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse"]] """The voice the model uses to respond. Voice cannot be changed during the session once the model has responded with audio at least once. Current voice options are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, and `verse`. """ class ClientSecretExpiresAfter(TypedDict, total=False): anchor: Required[Literal["created_at"]] """The anchor point for the ephemeral token expiration. Only `created_at` is currently supported. """ seconds: int """The number of seconds from the anchor point to the expiration. Select a value between `10` and `7200`. """ class ClientSecret(TypedDict, total=False): expires_after: ClientSecretExpiresAfter """Configuration for the ephemeral token expiration.""" class InputAudioNoiseReduction(TypedDict, total=False): type: Literal["near_field", "far_field"] """Type of noise reduction. `near_field` is for close-talking microphones such as headphones, `far_field` is for far-field microphones such as laptop or conference room microphones. """ class InputAudioTranscription(TypedDict, total=False): language: str """The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format will improve accuracy and latency. """ model: str """ The model to use for transcription, current options are `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, and `whisper-1`. """ prompt: str """ An optional text to guide the model's style or continue a previous audio segment. For `whisper-1`, the [prompt is a list of keywords](https://platform.openai.com/docs/guides/speech-to-text#prompting). For `gpt-4o-transcribe` models, the prompt is a free text string, for example "expect words related to technology". """ class Tool(TypedDict, total=False): description: str """ The description of the function, including guidance on when and how to call it, and guidance about what to tell the user when calling (if anything). """ name: str """The name of the function.""" parameters: object """Parameters of the function in JSON Schema.""" type: Literal["function"] """The type of the tool, i.e. `function`.""" class TracingTracingConfiguration(TypedDict, total=False): group_id: str """ The group id to attach to this trace to enable filtering and grouping in the traces dashboard. """ metadata: object """ The arbitrary metadata to attach to this trace to enable filtering in the traces dashboard. """ workflow_name: str """The name of the workflow to attach to this trace. This is used to name the trace in the traces dashboard. """ Tracing: TypeAlias = Union[Literal["auto"], TracingTracingConfiguration] class TurnDetection(TypedDict, total=False): create_response: bool """ Whether or not to automatically generate a response when a VAD stop event occurs. """ eagerness: Literal["low", "medium", "high", "auto"] """Used only for `semantic_vad` mode. The eagerness of the model to respond. `low` will wait longer for the user to continue speaking, `high` will respond more quickly. `auto` is the default and is equivalent to `medium`. """ interrupt_response: bool """ Whether or not to automatically interrupt any ongoing response with output to the default conversation (i.e. `conversation` of `auto`) when a VAD start event occurs. """ prefix_padding_ms: int """Used only for `server_vad` mode. Amount of audio to include before the VAD detected speech (in milliseconds). Defaults to 300ms. """ silence_duration_ms: int """Used only for `server_vad` mode. Duration of silence to detect speech stop (in milliseconds). Defaults to 500ms. With shorter values the model will respond more quickly, but may jump in on short pauses from the user. """ threshold: float """Used only for `server_vad` mode. Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A higher threshold will require louder audio to activate the model, and thus might perform better in noisy environments. """ type: Literal["server_vad", "semantic_vad"] """Type of turn detection.""" ================================================ FILE: src/openai/types/beta/realtime/session_create_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, TypeAlias from ...._models import BaseModel __all__ = [ "SessionCreateResponse", "ClientSecret", "InputAudioTranscription", "Tool", "Tracing", "TracingTracingConfiguration", "TurnDetection", ] class ClientSecret(BaseModel): expires_at: int """Timestamp for when the token expires. Currently, all tokens expire after one minute. """ value: str """ Ephemeral key usable in client environments to authenticate connections to the Realtime API. Use this in client-side environments rather than a standard API token, which should only be used server-side. """ class InputAudioTranscription(BaseModel): model: Optional[str] = None """The model to use for transcription.""" class Tool(BaseModel): description: Optional[str] = None """ The description of the function, including guidance on when and how to call it, and guidance about what to tell the user when calling (if anything). """ name: Optional[str] = None """The name of the function.""" parameters: Optional[object] = None """Parameters of the function in JSON Schema.""" type: Optional[Literal["function"]] = None """The type of the tool, i.e. `function`.""" class TracingTracingConfiguration(BaseModel): group_id: Optional[str] = None """ The group id to attach to this trace to enable filtering and grouping in the traces dashboard. """ metadata: Optional[object] = None """ The arbitrary metadata to attach to this trace to enable filtering in the traces dashboard. """ workflow_name: Optional[str] = None """The name of the workflow to attach to this trace. This is used to name the trace in the traces dashboard. """ Tracing: TypeAlias = Union[Literal["auto"], TracingTracingConfiguration] class TurnDetection(BaseModel): prefix_padding_ms: Optional[int] = None """Amount of audio to include before the VAD detected speech (in milliseconds). Defaults to 300ms. """ silence_duration_ms: Optional[int] = None """Duration of silence to detect speech stop (in milliseconds). Defaults to 500ms. With shorter values the model will respond more quickly, but may jump in on short pauses from the user. """ threshold: Optional[float] = None """Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A higher threshold will require louder audio to activate the model, and thus might perform better in noisy environments. """ type: Optional[str] = None """Type of turn detection, only `server_vad` is currently supported.""" class SessionCreateResponse(BaseModel): client_secret: ClientSecret """Ephemeral key returned by the API.""" input_audio_format: Optional[str] = None """The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`.""" input_audio_transcription: Optional[InputAudioTranscription] = None """ Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously and should be treated as rough guidance rather than the representation understood by the model. """ instructions: Optional[str] = None """The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. "be extremely succinct", "act friendly", "here are examples of good responses") and on audio behavior (e.g. "talk quickly", "inject emotion into your voice", "laugh frequently"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior. Note that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session. """ max_response_output_tokens: Union[int, Literal["inf"], None] = None """ Maximum number of output tokens for a single assistant response, inclusive of tool calls. Provide an integer between 1 and 4096 to limit output tokens, or `inf` for the maximum available tokens for a given model. Defaults to `inf`. """ modalities: Optional[List[Literal["text", "audio"]]] = None """The set of modalities the model can respond with. To disable audio, set this to ["text"]. """ output_audio_format: Optional[str] = None """The format of output audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`.""" speed: Optional[float] = None """The speed of the model's spoken response. 1.0 is the default speed. 0.25 is the minimum speed. 1.5 is the maximum speed. This value can only be changed in between model turns, not while a response is in progress. """ temperature: Optional[float] = None """Sampling temperature for the model, limited to [0.6, 1.2]. Defaults to 0.8.""" tool_choice: Optional[str] = None """How the model chooses tools. Options are `auto`, `none`, `required`, or specify a function. """ tools: Optional[List[Tool]] = None """Tools (functions) available to the model.""" tracing: Optional[Tracing] = None """Configuration options for tracing. Set to null to disable tracing. Once tracing is enabled for a session, the configuration cannot be modified. `auto` will create a trace for the session with default values for the workflow name, group id, and metadata. """ turn_detection: Optional[TurnDetection] = None """Configuration for turn detection. Can be set to `null` to turn off. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. """ voice: Union[str, Literal["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse"], None] = None """The voice the model uses to respond. Voice cannot be changed during the session once the model has responded with audio at least once. Current voice options are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, and `verse`. """ ================================================ FILE: src/openai/types/beta/realtime/session_created_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .session import Session from ...._models import BaseModel __all__ = ["SessionCreatedEvent"] class SessionCreatedEvent(BaseModel): event_id: str """The unique ID of the server event.""" session: Session """Realtime session object configuration.""" type: Literal["session.created"] """The event type, must be `session.created`.""" ================================================ FILE: src/openai/types/beta/realtime/session_update_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, TypeAlias from ...._models import BaseModel __all__ = [ "SessionUpdateEvent", "Session", "SessionClientSecret", "SessionClientSecretExpiresAfter", "SessionInputAudioNoiseReduction", "SessionInputAudioTranscription", "SessionTool", "SessionTracing", "SessionTracingTracingConfiguration", "SessionTurnDetection", ] class SessionClientSecretExpiresAfter(BaseModel): anchor: Literal["created_at"] """The anchor point for the ephemeral token expiration. Only `created_at` is currently supported. """ seconds: Optional[int] = None """The number of seconds from the anchor point to the expiration. Select a value between `10` and `7200`. """ class SessionClientSecret(BaseModel): expires_after: Optional[SessionClientSecretExpiresAfter] = None """Configuration for the ephemeral token expiration.""" class SessionInputAudioNoiseReduction(BaseModel): type: Optional[Literal["near_field", "far_field"]] = None """Type of noise reduction. `near_field` is for close-talking microphones such as headphones, `far_field` is for far-field microphones such as laptop or conference room microphones. """ class SessionInputAudioTranscription(BaseModel): language: Optional[str] = None """The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format will improve accuracy and latency. """ model: Optional[str] = None """ The model to use for transcription, current options are `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, and `whisper-1`. """ prompt: Optional[str] = None """ An optional text to guide the model's style or continue a previous audio segment. For `whisper-1`, the [prompt is a list of keywords](https://platform.openai.com/docs/guides/speech-to-text#prompting). For `gpt-4o-transcribe` models, the prompt is a free text string, for example "expect words related to technology". """ class SessionTool(BaseModel): description: Optional[str] = None """ The description of the function, including guidance on when and how to call it, and guidance about what to tell the user when calling (if anything). """ name: Optional[str] = None """The name of the function.""" parameters: Optional[object] = None """Parameters of the function in JSON Schema.""" type: Optional[Literal["function"]] = None """The type of the tool, i.e. `function`.""" class SessionTracingTracingConfiguration(BaseModel): group_id: Optional[str] = None """ The group id to attach to this trace to enable filtering and grouping in the traces dashboard. """ metadata: Optional[object] = None """ The arbitrary metadata to attach to this trace to enable filtering in the traces dashboard. """ workflow_name: Optional[str] = None """The name of the workflow to attach to this trace. This is used to name the trace in the traces dashboard. """ SessionTracing: TypeAlias = Union[Literal["auto"], SessionTracingTracingConfiguration] class SessionTurnDetection(BaseModel): create_response: Optional[bool] = None """ Whether or not to automatically generate a response when a VAD stop event occurs. """ eagerness: Optional[Literal["low", "medium", "high", "auto"]] = None """Used only for `semantic_vad` mode. The eagerness of the model to respond. `low` will wait longer for the user to continue speaking, `high` will respond more quickly. `auto` is the default and is equivalent to `medium`. """ interrupt_response: Optional[bool] = None """ Whether or not to automatically interrupt any ongoing response with output to the default conversation (i.e. `conversation` of `auto`) when a VAD start event occurs. """ prefix_padding_ms: Optional[int] = None """Used only for `server_vad` mode. Amount of audio to include before the VAD detected speech (in milliseconds). Defaults to 300ms. """ silence_duration_ms: Optional[int] = None """Used only for `server_vad` mode. Duration of silence to detect speech stop (in milliseconds). Defaults to 500ms. With shorter values the model will respond more quickly, but may jump in on short pauses from the user. """ threshold: Optional[float] = None """Used only for `server_vad` mode. Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A higher threshold will require louder audio to activate the model, and thus might perform better in noisy environments. """ type: Optional[Literal["server_vad", "semantic_vad"]] = None """Type of turn detection.""" class Session(BaseModel): client_secret: Optional[SessionClientSecret] = None """Configuration options for the generated client secret.""" input_audio_format: Optional[Literal["pcm16", "g711_ulaw", "g711_alaw"]] = None """The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`. For `pcm16`, input audio must be 16-bit PCM at a 24kHz sample rate, single channel (mono), and little-endian byte order. """ input_audio_noise_reduction: Optional[SessionInputAudioNoiseReduction] = None """Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. """ input_audio_transcription: Optional[SessionInputAudioTranscription] = None """ Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](https://platform.openai.com/docs/api-reference/audio/createTranscription) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service. """ instructions: Optional[str] = None """The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. "be extremely succinct", "act friendly", "here are examples of good responses") and on audio behavior (e.g. "talk quickly", "inject emotion into your voice", "laugh frequently"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior. Note that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session. """ max_response_output_tokens: Union[int, Literal["inf"], None] = None """ Maximum number of output tokens for a single assistant response, inclusive of tool calls. Provide an integer between 1 and 4096 to limit output tokens, or `inf` for the maximum available tokens for a given model. Defaults to `inf`. """ modalities: Optional[List[Literal["text", "audio"]]] = None """The set of modalities the model can respond with. To disable audio, set this to ["text"]. """ model: Optional[ Literal[ "gpt-realtime", "gpt-realtime-2025-08-28", "gpt-4o-realtime-preview", "gpt-4o-realtime-preview-2024-10-01", "gpt-4o-realtime-preview-2024-12-17", "gpt-4o-realtime-preview-2025-06-03", "gpt-4o-mini-realtime-preview", "gpt-4o-mini-realtime-preview-2024-12-17", ] ] = None """The Realtime model used for this session.""" output_audio_format: Optional[Literal["pcm16", "g711_ulaw", "g711_alaw"]] = None """The format of output audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`. For `pcm16`, output audio is sampled at a rate of 24kHz. """ speed: Optional[float] = None """The speed of the model's spoken response. 1.0 is the default speed. 0.25 is the minimum speed. 1.5 is the maximum speed. This value can only be changed in between model turns, not while a response is in progress. """ temperature: Optional[float] = None """Sampling temperature for the model, limited to [0.6, 1.2]. For audio models a temperature of 0.8 is highly recommended for best performance. """ tool_choice: Optional[str] = None """How the model chooses tools. Options are `auto`, `none`, `required`, or specify a function. """ tools: Optional[List[SessionTool]] = None """Tools (functions) available to the model.""" tracing: Optional[SessionTracing] = None """Configuration options for tracing. Set to null to disable tracing. Once tracing is enabled for a session, the configuration cannot be modified. `auto` will create a trace for the session with default values for the workflow name, group id, and metadata. """ turn_detection: Optional[SessionTurnDetection] = None """Configuration for turn detection, ether Server VAD or Semantic VAD. This can be set to `null` to turn off, in which case the client must manually trigger model response. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. Semantic VAD is more advanced and uses a turn detection model (in conjunction with VAD) to semantically estimate whether the user has finished speaking, then dynamically sets a timeout based on this probability. For example, if user audio trails off with "uhhm", the model will score a low probability of turn end and wait longer for the user to continue speaking. This can be useful for more natural conversations, but may have a higher latency. """ voice: Union[str, Literal["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse"], None] = None """The voice the model uses to respond. Voice cannot be changed during the session once the model has responded with audio at least once. Current voice options are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, and `verse`. """ class SessionUpdateEvent(BaseModel): session: Session """Realtime session object configuration.""" type: Literal["session.update"] """The event type, must be `session.update`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/beta/realtime/session_update_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List, Union, Iterable from typing_extensions import Literal, Required, TypeAlias, TypedDict __all__ = [ "SessionUpdateEventParam", "Session", "SessionClientSecret", "SessionClientSecretExpiresAfter", "SessionInputAudioNoiseReduction", "SessionInputAudioTranscription", "SessionTool", "SessionTracing", "SessionTracingTracingConfiguration", "SessionTurnDetection", ] class SessionClientSecretExpiresAfter(TypedDict, total=False): anchor: Required[Literal["created_at"]] """The anchor point for the ephemeral token expiration. Only `created_at` is currently supported. """ seconds: int """The number of seconds from the anchor point to the expiration. Select a value between `10` and `7200`. """ class SessionClientSecret(TypedDict, total=False): expires_after: SessionClientSecretExpiresAfter """Configuration for the ephemeral token expiration.""" class SessionInputAudioNoiseReduction(TypedDict, total=False): type: Literal["near_field", "far_field"] """Type of noise reduction. `near_field` is for close-talking microphones such as headphones, `far_field` is for far-field microphones such as laptop or conference room microphones. """ class SessionInputAudioTranscription(TypedDict, total=False): language: str """The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format will improve accuracy and latency. """ model: str """ The model to use for transcription, current options are `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, and `whisper-1`. """ prompt: str """ An optional text to guide the model's style or continue a previous audio segment. For `whisper-1`, the [prompt is a list of keywords](https://platform.openai.com/docs/guides/speech-to-text#prompting). For `gpt-4o-transcribe` models, the prompt is a free text string, for example "expect words related to technology". """ class SessionTool(TypedDict, total=False): description: str """ The description of the function, including guidance on when and how to call it, and guidance about what to tell the user when calling (if anything). """ name: str """The name of the function.""" parameters: object """Parameters of the function in JSON Schema.""" type: Literal["function"] """The type of the tool, i.e. `function`.""" class SessionTracingTracingConfiguration(TypedDict, total=False): group_id: str """ The group id to attach to this trace to enable filtering and grouping in the traces dashboard. """ metadata: object """ The arbitrary metadata to attach to this trace to enable filtering in the traces dashboard. """ workflow_name: str """The name of the workflow to attach to this trace. This is used to name the trace in the traces dashboard. """ SessionTracing: TypeAlias = Union[Literal["auto"], SessionTracingTracingConfiguration] class SessionTurnDetection(TypedDict, total=False): create_response: bool """ Whether or not to automatically generate a response when a VAD stop event occurs. """ eagerness: Literal["low", "medium", "high", "auto"] """Used only for `semantic_vad` mode. The eagerness of the model to respond. `low` will wait longer for the user to continue speaking, `high` will respond more quickly. `auto` is the default and is equivalent to `medium`. """ interrupt_response: bool """ Whether or not to automatically interrupt any ongoing response with output to the default conversation (i.e. `conversation` of `auto`) when a VAD start event occurs. """ prefix_padding_ms: int """Used only for `server_vad` mode. Amount of audio to include before the VAD detected speech (in milliseconds). Defaults to 300ms. """ silence_duration_ms: int """Used only for `server_vad` mode. Duration of silence to detect speech stop (in milliseconds). Defaults to 500ms. With shorter values the model will respond more quickly, but may jump in on short pauses from the user. """ threshold: float """Used only for `server_vad` mode. Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A higher threshold will require louder audio to activate the model, and thus might perform better in noisy environments. """ type: Literal["server_vad", "semantic_vad"] """Type of turn detection.""" class Session(TypedDict, total=False): client_secret: SessionClientSecret """Configuration options for the generated client secret.""" input_audio_format: Literal["pcm16", "g711_ulaw", "g711_alaw"] """The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`. For `pcm16`, input audio must be 16-bit PCM at a 24kHz sample rate, single channel (mono), and little-endian byte order. """ input_audio_noise_reduction: SessionInputAudioNoiseReduction """Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. """ input_audio_transcription: SessionInputAudioTranscription """ Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](https://platform.openai.com/docs/api-reference/audio/createTranscription) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service. """ instructions: str """The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. "be extremely succinct", "act friendly", "here are examples of good responses") and on audio behavior (e.g. "talk quickly", "inject emotion into your voice", "laugh frequently"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior. Note that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session. """ max_response_output_tokens: Union[int, Literal["inf"]] """ Maximum number of output tokens for a single assistant response, inclusive of tool calls. Provide an integer between 1 and 4096 to limit output tokens, or `inf` for the maximum available tokens for a given model. Defaults to `inf`. """ modalities: List[Literal["text", "audio"]] """The set of modalities the model can respond with. To disable audio, set this to ["text"]. """ model: Literal[ "gpt-realtime", "gpt-realtime-2025-08-28", "gpt-4o-realtime-preview", "gpt-4o-realtime-preview-2024-10-01", "gpt-4o-realtime-preview-2024-12-17", "gpt-4o-realtime-preview-2025-06-03", "gpt-4o-mini-realtime-preview", "gpt-4o-mini-realtime-preview-2024-12-17", ] """The Realtime model used for this session.""" output_audio_format: Literal["pcm16", "g711_ulaw", "g711_alaw"] """The format of output audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`. For `pcm16`, output audio is sampled at a rate of 24kHz. """ speed: float """The speed of the model's spoken response. 1.0 is the default speed. 0.25 is the minimum speed. 1.5 is the maximum speed. This value can only be changed in between model turns, not while a response is in progress. """ temperature: float """Sampling temperature for the model, limited to [0.6, 1.2]. For audio models a temperature of 0.8 is highly recommended for best performance. """ tool_choice: str """How the model chooses tools. Options are `auto`, `none`, `required`, or specify a function. """ tools: Iterable[SessionTool] """Tools (functions) available to the model.""" tracing: SessionTracing """Configuration options for tracing. Set to null to disable tracing. Once tracing is enabled for a session, the configuration cannot be modified. `auto` will create a trace for the session with default values for the workflow name, group id, and metadata. """ turn_detection: SessionTurnDetection """Configuration for turn detection, ether Server VAD or Semantic VAD. This can be set to `null` to turn off, in which case the client must manually trigger model response. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. Semantic VAD is more advanced and uses a turn detection model (in conjunction with VAD) to semantically estimate whether the user has finished speaking, then dynamically sets a timeout based on this probability. For example, if user audio trails off with "uhhm", the model will score a low probability of turn end and wait longer for the user to continue speaking. This can be useful for more natural conversations, but may have a higher latency. """ voice: Union[str, Literal["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse"]] """The voice the model uses to respond. Voice cannot be changed during the session once the model has responded with audio at least once. Current voice options are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, and `verse`. """ class SessionUpdateEventParam(TypedDict, total=False): session: Required[Session] """Realtime session object configuration.""" type: Required[Literal["session.update"]] """The event type, must be `session.update`.""" event_id: str """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/beta/realtime/session_updated_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .session import Session from ...._models import BaseModel __all__ = ["SessionUpdatedEvent"] class SessionUpdatedEvent(BaseModel): event_id: str """The unique ID of the server event.""" session: Session """Realtime session object configuration.""" type: Literal["session.updated"] """The event type, must be `session.updated`.""" ================================================ FILE: src/openai/types/beta/realtime/transcription_session.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["TranscriptionSession", "ClientSecret", "InputAudioTranscription", "TurnDetection"] class ClientSecret(BaseModel): expires_at: int """Timestamp for when the token expires. Currently, all tokens expire after one minute. """ value: str """ Ephemeral key usable in client environments to authenticate connections to the Realtime API. Use this in client-side environments rather than a standard API token, which should only be used server-side. """ class InputAudioTranscription(BaseModel): language: Optional[str] = None """The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format will improve accuracy and latency. """ model: Optional[Literal["gpt-4o-transcribe", "gpt-4o-mini-transcribe", "whisper-1"]] = None """The model to use for transcription. Can be `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, or `whisper-1`. """ prompt: Optional[str] = None """An optional text to guide the model's style or continue a previous audio segment. The [prompt](https://platform.openai.com/docs/guides/speech-to-text#prompting) should match the audio language. """ class TurnDetection(BaseModel): prefix_padding_ms: Optional[int] = None """Amount of audio to include before the VAD detected speech (in milliseconds). Defaults to 300ms. """ silence_duration_ms: Optional[int] = None """Duration of silence to detect speech stop (in milliseconds). Defaults to 500ms. With shorter values the model will respond more quickly, but may jump in on short pauses from the user. """ threshold: Optional[float] = None """Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A higher threshold will require louder audio to activate the model, and thus might perform better in noisy environments. """ type: Optional[str] = None """Type of turn detection, only `server_vad` is currently supported.""" class TranscriptionSession(BaseModel): client_secret: ClientSecret """Ephemeral key returned by the API. Only present when the session is created on the server via REST API. """ input_audio_format: Optional[str] = None """The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`.""" input_audio_transcription: Optional[InputAudioTranscription] = None """Configuration of the transcription model.""" modalities: Optional[List[Literal["text", "audio"]]] = None """The set of modalities the model can respond with. To disable audio, set this to ["text"]. """ turn_detection: Optional[TurnDetection] = None """Configuration for turn detection. Can be set to `null` to turn off. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. """ ================================================ FILE: src/openai/types/beta/realtime/transcription_session_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List from typing_extensions import Literal, TypedDict __all__ = [ "TranscriptionSessionCreateParams", "ClientSecret", "ClientSecretExpiresAt", "InputAudioNoiseReduction", "InputAudioTranscription", "TurnDetection", ] class TranscriptionSessionCreateParams(TypedDict, total=False): client_secret: ClientSecret """Configuration options for the generated client secret.""" include: List[str] """The set of items to include in the transcription. Current available items are: - `item.input_audio_transcription.logprobs` """ input_audio_format: Literal["pcm16", "g711_ulaw", "g711_alaw"] """The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`. For `pcm16`, input audio must be 16-bit PCM at a 24kHz sample rate, single channel (mono), and little-endian byte order. """ input_audio_noise_reduction: InputAudioNoiseReduction """Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. """ input_audio_transcription: InputAudioTranscription """Configuration for input audio transcription. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service. """ modalities: List[Literal["text", "audio"]] """The set of modalities the model can respond with. To disable audio, set this to ["text"]. """ turn_detection: TurnDetection """Configuration for turn detection, ether Server VAD or Semantic VAD. This can be set to `null` to turn off, in which case the client must manually trigger model response. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. Semantic VAD is more advanced and uses a turn detection model (in conjunction with VAD) to semantically estimate whether the user has finished speaking, then dynamically sets a timeout based on this probability. For example, if user audio trails off with "uhhm", the model will score a low probability of turn end and wait longer for the user to continue speaking. This can be useful for more natural conversations, but may have a higher latency. """ class ClientSecretExpiresAt(TypedDict, total=False): anchor: Literal["created_at"] """The anchor point for the ephemeral token expiration. Only `created_at` is currently supported. """ seconds: int """The number of seconds from the anchor point to the expiration. Select a value between `10` and `7200`. """ class ClientSecret(TypedDict, total=False): expires_at: ClientSecretExpiresAt """Configuration for the ephemeral token expiration.""" class InputAudioNoiseReduction(TypedDict, total=False): type: Literal["near_field", "far_field"] """Type of noise reduction. `near_field` is for close-talking microphones such as headphones, `far_field` is for far-field microphones such as laptop or conference room microphones. """ class InputAudioTranscription(TypedDict, total=False): language: str """The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format will improve accuracy and latency. """ model: Literal["gpt-4o-transcribe", "gpt-4o-mini-transcribe", "whisper-1"] """ The model to use for transcription, current options are `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, and `whisper-1`. """ prompt: str """ An optional text to guide the model's style or continue a previous audio segment. For `whisper-1`, the [prompt is a list of keywords](https://platform.openai.com/docs/guides/speech-to-text#prompting). For `gpt-4o-transcribe` models, the prompt is a free text string, for example "expect words related to technology". """ class TurnDetection(TypedDict, total=False): create_response: bool """Whether or not to automatically generate a response when a VAD stop event occurs. Not available for transcription sessions. """ eagerness: Literal["low", "medium", "high", "auto"] """Used only for `semantic_vad` mode. The eagerness of the model to respond. `low` will wait longer for the user to continue speaking, `high` will respond more quickly. `auto` is the default and is equivalent to `medium`. """ interrupt_response: bool """ Whether or not to automatically interrupt any ongoing response with output to the default conversation (i.e. `conversation` of `auto`) when a VAD start event occurs. Not available for transcription sessions. """ prefix_padding_ms: int """Used only for `server_vad` mode. Amount of audio to include before the VAD detected speech (in milliseconds). Defaults to 300ms. """ silence_duration_ms: int """Used only for `server_vad` mode. Duration of silence to detect speech stop (in milliseconds). Defaults to 500ms. With shorter values the model will respond more quickly, but may jump in on short pauses from the user. """ threshold: float """Used only for `server_vad` mode. Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A higher threshold will require louder audio to activate the model, and thus might perform better in noisy environments. """ type: Literal["server_vad", "semantic_vad"] """Type of turn detection.""" ================================================ FILE: src/openai/types/beta/realtime/transcription_session_update.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = [ "TranscriptionSessionUpdate", "Session", "SessionClientSecret", "SessionClientSecretExpiresAt", "SessionInputAudioNoiseReduction", "SessionInputAudioTranscription", "SessionTurnDetection", ] class SessionClientSecretExpiresAt(BaseModel): anchor: Optional[Literal["created_at"]] = None """The anchor point for the ephemeral token expiration. Only `created_at` is currently supported. """ seconds: Optional[int] = None """The number of seconds from the anchor point to the expiration. Select a value between `10` and `7200`. """ class SessionClientSecret(BaseModel): expires_at: Optional[SessionClientSecretExpiresAt] = None """Configuration for the ephemeral token expiration.""" class SessionInputAudioNoiseReduction(BaseModel): type: Optional[Literal["near_field", "far_field"]] = None """Type of noise reduction. `near_field` is for close-talking microphones such as headphones, `far_field` is for far-field microphones such as laptop or conference room microphones. """ class SessionInputAudioTranscription(BaseModel): language: Optional[str] = None """The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format will improve accuracy and latency. """ model: Optional[Literal["gpt-4o-transcribe", "gpt-4o-mini-transcribe", "whisper-1"]] = None """ The model to use for transcription, current options are `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, and `whisper-1`. """ prompt: Optional[str] = None """ An optional text to guide the model's style or continue a previous audio segment. For `whisper-1`, the [prompt is a list of keywords](https://platform.openai.com/docs/guides/speech-to-text#prompting). For `gpt-4o-transcribe` models, the prompt is a free text string, for example "expect words related to technology". """ class SessionTurnDetection(BaseModel): create_response: Optional[bool] = None """Whether or not to automatically generate a response when a VAD stop event occurs. Not available for transcription sessions. """ eagerness: Optional[Literal["low", "medium", "high", "auto"]] = None """Used only for `semantic_vad` mode. The eagerness of the model to respond. `low` will wait longer for the user to continue speaking, `high` will respond more quickly. `auto` is the default and is equivalent to `medium`. """ interrupt_response: Optional[bool] = None """ Whether or not to automatically interrupt any ongoing response with output to the default conversation (i.e. `conversation` of `auto`) when a VAD start event occurs. Not available for transcription sessions. """ prefix_padding_ms: Optional[int] = None """Used only for `server_vad` mode. Amount of audio to include before the VAD detected speech (in milliseconds). Defaults to 300ms. """ silence_duration_ms: Optional[int] = None """Used only for `server_vad` mode. Duration of silence to detect speech stop (in milliseconds). Defaults to 500ms. With shorter values the model will respond more quickly, but may jump in on short pauses from the user. """ threshold: Optional[float] = None """Used only for `server_vad` mode. Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A higher threshold will require louder audio to activate the model, and thus might perform better in noisy environments. """ type: Optional[Literal["server_vad", "semantic_vad"]] = None """Type of turn detection.""" class Session(BaseModel): client_secret: Optional[SessionClientSecret] = None """Configuration options for the generated client secret.""" include: Optional[List[str]] = None """The set of items to include in the transcription. Current available items are: - `item.input_audio_transcription.logprobs` """ input_audio_format: Optional[Literal["pcm16", "g711_ulaw", "g711_alaw"]] = None """The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`. For `pcm16`, input audio must be 16-bit PCM at a 24kHz sample rate, single channel (mono), and little-endian byte order. """ input_audio_noise_reduction: Optional[SessionInputAudioNoiseReduction] = None """Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. """ input_audio_transcription: Optional[SessionInputAudioTranscription] = None """Configuration for input audio transcription. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service. """ modalities: Optional[List[Literal["text", "audio"]]] = None """The set of modalities the model can respond with. To disable audio, set this to ["text"]. """ turn_detection: Optional[SessionTurnDetection] = None """Configuration for turn detection, ether Server VAD or Semantic VAD. This can be set to `null` to turn off, in which case the client must manually trigger model response. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. Semantic VAD is more advanced and uses a turn detection model (in conjunction with VAD) to semantically estimate whether the user has finished speaking, then dynamically sets a timeout based on this probability. For example, if user audio trails off with "uhhm", the model will score a low probability of turn end and wait longer for the user to continue speaking. This can be useful for more natural conversations, but may have a higher latency. """ class TranscriptionSessionUpdate(BaseModel): session: Session """Realtime transcription session object configuration.""" type: Literal["transcription_session.update"] """The event type, must be `transcription_session.update`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/beta/realtime/transcription_session_update_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List from typing_extensions import Literal, Required, TypedDict __all__ = [ "TranscriptionSessionUpdateParam", "Session", "SessionClientSecret", "SessionClientSecretExpiresAt", "SessionInputAudioNoiseReduction", "SessionInputAudioTranscription", "SessionTurnDetection", ] class SessionClientSecretExpiresAt(TypedDict, total=False): anchor: Literal["created_at"] """The anchor point for the ephemeral token expiration. Only `created_at` is currently supported. """ seconds: int """The number of seconds from the anchor point to the expiration. Select a value between `10` and `7200`. """ class SessionClientSecret(TypedDict, total=False): expires_at: SessionClientSecretExpiresAt """Configuration for the ephemeral token expiration.""" class SessionInputAudioNoiseReduction(TypedDict, total=False): type: Literal["near_field", "far_field"] """Type of noise reduction. `near_field` is for close-talking microphones such as headphones, `far_field` is for far-field microphones such as laptop or conference room microphones. """ class SessionInputAudioTranscription(TypedDict, total=False): language: str """The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format will improve accuracy and latency. """ model: Literal["gpt-4o-transcribe", "gpt-4o-mini-transcribe", "whisper-1"] """ The model to use for transcription, current options are `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, and `whisper-1`. """ prompt: str """ An optional text to guide the model's style or continue a previous audio segment. For `whisper-1`, the [prompt is a list of keywords](https://platform.openai.com/docs/guides/speech-to-text#prompting). For `gpt-4o-transcribe` models, the prompt is a free text string, for example "expect words related to technology". """ class SessionTurnDetection(TypedDict, total=False): create_response: bool """Whether or not to automatically generate a response when a VAD stop event occurs. Not available for transcription sessions. """ eagerness: Literal["low", "medium", "high", "auto"] """Used only for `semantic_vad` mode. The eagerness of the model to respond. `low` will wait longer for the user to continue speaking, `high` will respond more quickly. `auto` is the default and is equivalent to `medium`. """ interrupt_response: bool """ Whether or not to automatically interrupt any ongoing response with output to the default conversation (i.e. `conversation` of `auto`) when a VAD start event occurs. Not available for transcription sessions. """ prefix_padding_ms: int """Used only for `server_vad` mode. Amount of audio to include before the VAD detected speech (in milliseconds). Defaults to 300ms. """ silence_duration_ms: int """Used only for `server_vad` mode. Duration of silence to detect speech stop (in milliseconds). Defaults to 500ms. With shorter values the model will respond more quickly, but may jump in on short pauses from the user. """ threshold: float """Used only for `server_vad` mode. Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A higher threshold will require louder audio to activate the model, and thus might perform better in noisy environments. """ type: Literal["server_vad", "semantic_vad"] """Type of turn detection.""" class Session(TypedDict, total=False): client_secret: SessionClientSecret """Configuration options for the generated client secret.""" include: List[str] """The set of items to include in the transcription. Current available items are: - `item.input_audio_transcription.logprobs` """ input_audio_format: Literal["pcm16", "g711_ulaw", "g711_alaw"] """The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`. For `pcm16`, input audio must be 16-bit PCM at a 24kHz sample rate, single channel (mono), and little-endian byte order. """ input_audio_noise_reduction: SessionInputAudioNoiseReduction """Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. """ input_audio_transcription: SessionInputAudioTranscription """Configuration for input audio transcription. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service. """ modalities: List[Literal["text", "audio"]] """The set of modalities the model can respond with. To disable audio, set this to ["text"]. """ turn_detection: SessionTurnDetection """Configuration for turn detection, ether Server VAD or Semantic VAD. This can be set to `null` to turn off, in which case the client must manually trigger model response. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. Semantic VAD is more advanced and uses a turn detection model (in conjunction with VAD) to semantically estimate whether the user has finished speaking, then dynamically sets a timeout based on this probability. For example, if user audio trails off with "uhhm", the model will score a low probability of turn end and wait longer for the user to continue speaking. This can be useful for more natural conversations, but may have a higher latency. """ class TranscriptionSessionUpdateParam(TypedDict, total=False): session: Required[Session] """Realtime transcription session object configuration.""" type: Required[Literal["transcription_session.update"]] """The event type, must be `transcription_session.update`.""" event_id: str """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/beta/realtime/transcription_session_updated_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel from .transcription_session import TranscriptionSession __all__ = ["TranscriptionSessionUpdatedEvent"] class TranscriptionSessionUpdatedEvent(BaseModel): event_id: str """The unique ID of the server event.""" session: TranscriptionSession """A new Realtime transcription session configuration. When a session is created on the server via REST API, the session object also contains an ephemeral key. Default TTL for keys is 10 minutes. This property is not present when a session is updated via the WebSocket API. """ type: Literal["transcription_session.updated"] """The event type, must be `transcription_session.updated`.""" ================================================ FILE: src/openai/types/beta/thread.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel from ..shared.metadata import Metadata __all__ = ["Thread", "ToolResources", "ToolResourcesCodeInterpreter", "ToolResourcesFileSearch"] class ToolResourcesCodeInterpreter(BaseModel): file_ids: Optional[List[str]] = None """ A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool. """ class ToolResourcesFileSearch(BaseModel): vector_store_ids: Optional[List[str]] = None """ The [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) attached to this thread. There can be a maximum of 1 vector store attached to the thread. """ class ToolResources(BaseModel): """ A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. """ code_interpreter: Optional[ToolResourcesCodeInterpreter] = None file_search: Optional[ToolResourcesFileSearch] = None class Thread(BaseModel): """ Represents a thread that contains [messages](https://platform.openai.com/docs/api-reference/messages). """ id: str """The identifier, which can be referenced in API endpoints.""" created_at: int """The Unix timestamp (in seconds) for when the thread was created.""" metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ object: Literal["thread"] """The object type, which is always `thread`.""" tool_resources: Optional[ToolResources] = None """ A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. """ ================================================ FILE: src/openai/types/beta/thread_create_and_run_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import SequenceNotStr from ..shared.chat_model import ChatModel from .assistant_tool_param import AssistantToolParam from ..shared_params.metadata import Metadata from .code_interpreter_tool_param import CodeInterpreterToolParam from .assistant_tool_choice_option_param import AssistantToolChoiceOptionParam from .threads.message_content_part_param import MessageContentPartParam from .assistant_response_format_option_param import AssistantResponseFormatOptionParam __all__ = [ "ThreadCreateAndRunParamsBase", "Thread", "ThreadMessage", "ThreadMessageAttachment", "ThreadMessageAttachmentTool", "ThreadMessageAttachmentToolFileSearch", "ThreadToolResources", "ThreadToolResourcesCodeInterpreter", "ThreadToolResourcesFileSearch", "ThreadToolResourcesFileSearchVectorStore", "ThreadToolResourcesFileSearchVectorStoreChunkingStrategy", "ThreadToolResourcesFileSearchVectorStoreChunkingStrategyAuto", "ThreadToolResourcesFileSearchVectorStoreChunkingStrategyStatic", "ThreadToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic", "ToolResources", "ToolResourcesCodeInterpreter", "ToolResourcesFileSearch", "TruncationStrategy", "ThreadCreateAndRunParamsNonStreaming", "ThreadCreateAndRunParamsStreaming", ] class ThreadCreateAndRunParamsBase(TypedDict, total=False): assistant_id: Required[str] """ The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to use to execute this run. """ instructions: Optional[str] """Override the default system message of the assistant. This is useful for modifying the behavior on a per-run basis. """ max_completion_tokens: Optional[int] """ The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. """ max_prompt_tokens: Optional[int] """The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. """ metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ model: Union[str, ChatModel, None] """ The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used. """ parallel_tool_calls: bool """ Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. """ response_format: Optional[AssistantResponseFormatOptionParam] """Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. """ temperature: Optional[float] """What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. """ thread: Thread """Options to create a new thread. If no thread is provided when running a request, an empty thread will be created. """ tool_choice: Optional[AssistantToolChoiceOptionParam] """ Controls which (if any) tool is called by the model. `none` means the model will not call any tools and instead generates a message. `auto` is the default value and means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools before responding to the user. Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. """ tool_resources: Optional[ToolResources] """A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. """ tools: Optional[Iterable[AssistantToolParam]] """Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis. """ top_p: Optional[float] """ An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. """ truncation_strategy: Optional[TruncationStrategy] """Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run. """ class ThreadMessageAttachmentToolFileSearch(TypedDict, total=False): type: Required[Literal["file_search"]] """The type of tool being defined: `file_search`""" ThreadMessageAttachmentTool: TypeAlias = Union[CodeInterpreterToolParam, ThreadMessageAttachmentToolFileSearch] class ThreadMessageAttachment(TypedDict, total=False): file_id: str """The ID of the file to attach to the message.""" tools: Iterable[ThreadMessageAttachmentTool] """The tools to add this file to.""" class ThreadMessage(TypedDict, total=False): content: Required[Union[str, Iterable[MessageContentPartParam]]] """The text contents of the message.""" role: Required[Literal["user", "assistant"]] """The role of the entity that is creating the message. Allowed values include: - `user`: Indicates the message is sent by an actual user and should be used in most cases to represent user-generated messages. - `assistant`: Indicates the message is generated by the assistant. Use this value to insert messages from the assistant into the conversation. """ attachments: Optional[Iterable[ThreadMessageAttachment]] """A list of files attached to the message, and the tools they should be added to.""" metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ class ThreadToolResourcesCodeInterpreter(TypedDict, total=False): file_ids: SequenceNotStr[str] """ A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool. """ class ThreadToolResourcesFileSearchVectorStoreChunkingStrategyAuto(TypedDict, total=False): """The default strategy. This strategy currently uses a `max_chunk_size_tokens` of `800` and `chunk_overlap_tokens` of `400`. """ type: Required[Literal["auto"]] """Always `auto`.""" class ThreadToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic(TypedDict, total=False): chunk_overlap_tokens: Required[int] """The number of tokens that overlap between chunks. The default value is `400`. Note that the overlap must not exceed half of `max_chunk_size_tokens`. """ max_chunk_size_tokens: Required[int] """The maximum number of tokens in each chunk. The default value is `800`. The minimum value is `100` and the maximum value is `4096`. """ class ThreadToolResourcesFileSearchVectorStoreChunkingStrategyStatic(TypedDict, total=False): static: Required[ThreadToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic] type: Required[Literal["static"]] """Always `static`.""" ThreadToolResourcesFileSearchVectorStoreChunkingStrategy: TypeAlias = Union[ ThreadToolResourcesFileSearchVectorStoreChunkingStrategyAuto, ThreadToolResourcesFileSearchVectorStoreChunkingStrategyStatic, ] class ThreadToolResourcesFileSearchVectorStore(TypedDict, total=False): chunking_strategy: ThreadToolResourcesFileSearchVectorStoreChunkingStrategy """The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. """ file_ids: SequenceNotStr[str] """ A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to add to the vector store. For vector stores created before Nov 2025, there can be a maximum of 10,000 files in a vector store. For vector stores created starting in Nov 2025, the limit is 100,000,000 files. """ metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ class ThreadToolResourcesFileSearch(TypedDict, total=False): vector_store_ids: SequenceNotStr[str] """ The [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) attached to this thread. There can be a maximum of 1 vector store attached to the thread. """ vector_stores: Iterable[ThreadToolResourcesFileSearchVectorStore] """ A helper to create a [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) with file_ids and attach it to this thread. There can be a maximum of 1 vector store attached to the thread. """ class ThreadToolResources(TypedDict, total=False): """ A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. """ code_interpreter: ThreadToolResourcesCodeInterpreter file_search: ThreadToolResourcesFileSearch class Thread(TypedDict, total=False): """Options to create a new thread. If no thread is provided when running a request, an empty thread will be created. """ messages: Iterable[ThreadMessage] """ A list of [messages](https://platform.openai.com/docs/api-reference/messages) to start the thread with. """ metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ tool_resources: Optional[ThreadToolResources] """ A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. """ class ToolResourcesCodeInterpreter(TypedDict, total=False): file_ids: SequenceNotStr[str] """ A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool. """ class ToolResourcesFileSearch(TypedDict, total=False): vector_store_ids: SequenceNotStr[str] """ The ID of the [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) attached to this assistant. There can be a maximum of 1 vector store attached to the assistant. """ class ToolResources(TypedDict, total=False): """A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. """ code_interpreter: ToolResourcesCodeInterpreter file_search: ToolResourcesFileSearch class TruncationStrategy(TypedDict, total=False): """Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run. """ type: Required[Literal["auto", "last_messages"]] """The truncation strategy to use for the thread. The default is `auto`. If set to `last_messages`, the thread will be truncated to the n most recent messages in the thread. When set to `auto`, messages in the middle of the thread will be dropped to fit the context length of the model, `max_prompt_tokens`. """ last_messages: Optional[int] """ The number of most recent messages from the thread when constructing the context for the run. """ class ThreadCreateAndRunParamsNonStreaming(ThreadCreateAndRunParamsBase, total=False): stream: Optional[Literal[False]] """ If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. """ class ThreadCreateAndRunParamsStreaming(ThreadCreateAndRunParamsBase): stream: Required[Literal[True]] """ If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. """ ThreadCreateAndRunParams = Union[ThreadCreateAndRunParamsNonStreaming, ThreadCreateAndRunParamsStreaming] ================================================ FILE: src/openai/types/beta/thread_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import SequenceNotStr from ..shared_params.metadata import Metadata from .code_interpreter_tool_param import CodeInterpreterToolParam from .threads.message_content_part_param import MessageContentPartParam __all__ = [ "ThreadCreateParams", "Message", "MessageAttachment", "MessageAttachmentTool", "MessageAttachmentToolFileSearch", "ToolResources", "ToolResourcesCodeInterpreter", "ToolResourcesFileSearch", "ToolResourcesFileSearchVectorStore", "ToolResourcesFileSearchVectorStoreChunkingStrategy", "ToolResourcesFileSearchVectorStoreChunkingStrategyAuto", "ToolResourcesFileSearchVectorStoreChunkingStrategyStatic", "ToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic", ] class ThreadCreateParams(TypedDict, total=False): messages: Iterable[Message] """ A list of [messages](https://platform.openai.com/docs/api-reference/messages) to start the thread with. """ metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ tool_resources: Optional[ToolResources] """ A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. """ class MessageAttachmentToolFileSearch(TypedDict, total=False): type: Required[Literal["file_search"]] """The type of tool being defined: `file_search`""" MessageAttachmentTool: TypeAlias = Union[CodeInterpreterToolParam, MessageAttachmentToolFileSearch] class MessageAttachment(TypedDict, total=False): file_id: str """The ID of the file to attach to the message.""" tools: Iterable[MessageAttachmentTool] """The tools to add this file to.""" class Message(TypedDict, total=False): content: Required[Union[str, Iterable[MessageContentPartParam]]] """The text contents of the message.""" role: Required[Literal["user", "assistant"]] """The role of the entity that is creating the message. Allowed values include: - `user`: Indicates the message is sent by an actual user and should be used in most cases to represent user-generated messages. - `assistant`: Indicates the message is generated by the assistant. Use this value to insert messages from the assistant into the conversation. """ attachments: Optional[Iterable[MessageAttachment]] """A list of files attached to the message, and the tools they should be added to.""" metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ class ToolResourcesCodeInterpreter(TypedDict, total=False): file_ids: SequenceNotStr[str] """ A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool. """ class ToolResourcesFileSearchVectorStoreChunkingStrategyAuto(TypedDict, total=False): """The default strategy. This strategy currently uses a `max_chunk_size_tokens` of `800` and `chunk_overlap_tokens` of `400`. """ type: Required[Literal["auto"]] """Always `auto`.""" class ToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic(TypedDict, total=False): chunk_overlap_tokens: Required[int] """The number of tokens that overlap between chunks. The default value is `400`. Note that the overlap must not exceed half of `max_chunk_size_tokens`. """ max_chunk_size_tokens: Required[int] """The maximum number of tokens in each chunk. The default value is `800`. The minimum value is `100` and the maximum value is `4096`. """ class ToolResourcesFileSearchVectorStoreChunkingStrategyStatic(TypedDict, total=False): static: Required[ToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic] type: Required[Literal["static"]] """Always `static`.""" ToolResourcesFileSearchVectorStoreChunkingStrategy: TypeAlias = Union[ ToolResourcesFileSearchVectorStoreChunkingStrategyAuto, ToolResourcesFileSearchVectorStoreChunkingStrategyStatic ] class ToolResourcesFileSearchVectorStore(TypedDict, total=False): chunking_strategy: ToolResourcesFileSearchVectorStoreChunkingStrategy """The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. """ file_ids: SequenceNotStr[str] """ A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to add to the vector store. For vector stores created before Nov 2025, there can be a maximum of 10,000 files in a vector store. For vector stores created starting in Nov 2025, the limit is 100,000,000 files. """ metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ class ToolResourcesFileSearch(TypedDict, total=False): vector_store_ids: SequenceNotStr[str] """ The [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) attached to this thread. There can be a maximum of 1 vector store attached to the thread. """ vector_stores: Iterable[ToolResourcesFileSearchVectorStore] """ A helper to create a [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) with file_ids and attach it to this thread. There can be a maximum of 1 vector store attached to the thread. """ class ToolResources(TypedDict, total=False): """ A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. """ code_interpreter: ToolResourcesCodeInterpreter file_search: ToolResourcesFileSearch ================================================ FILE: src/openai/types/beta/thread_deleted.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ThreadDeleted"] class ThreadDeleted(BaseModel): id: str deleted: bool object: Literal["thread.deleted"] ================================================ FILE: src/openai/types/beta/thread_update_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import TypedDict from ..._types import SequenceNotStr from ..shared_params.metadata import Metadata __all__ = ["ThreadUpdateParams", "ToolResources", "ToolResourcesCodeInterpreter", "ToolResourcesFileSearch"] class ThreadUpdateParams(TypedDict, total=False): metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ tool_resources: Optional[ToolResources] """ A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. """ class ToolResourcesCodeInterpreter(TypedDict, total=False): file_ids: SequenceNotStr[str] """ A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool. """ class ToolResourcesFileSearch(TypedDict, total=False): vector_store_ids: SequenceNotStr[str] """ The [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) attached to this thread. There can be a maximum of 1 vector store attached to the thread. """ class ToolResources(TypedDict, total=False): """ A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs. """ code_interpreter: ToolResourcesCodeInterpreter file_search: ToolResourcesFileSearch ================================================ FILE: src/openai/types/beta/threads/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .run import Run as Run from .text import Text as Text from .message import Message as Message from .image_url import ImageURL as ImageURL from .annotation import Annotation as Annotation from .image_file import ImageFile as ImageFile from .run_status import RunStatus as RunStatus from .text_delta import TextDelta as TextDelta from .message_delta import MessageDelta as MessageDelta from .image_url_delta import ImageURLDelta as ImageURLDelta from .image_url_param import ImageURLParam as ImageURLParam from .message_content import MessageContent as MessageContent from .message_deleted import MessageDeleted as MessageDeleted from .run_list_params import RunListParams as RunListParams from .annotation_delta import AnnotationDelta as AnnotationDelta from .image_file_delta import ImageFileDelta as ImageFileDelta from .image_file_param import ImageFileParam as ImageFileParam from .text_delta_block import TextDeltaBlock as TextDeltaBlock from .run_create_params import RunCreateParams as RunCreateParams from .run_update_params import RunUpdateParams as RunUpdateParams from .text_content_block import TextContentBlock as TextContentBlock from .message_delta_event import MessageDeltaEvent as MessageDeltaEvent from .message_list_params import MessageListParams as MessageListParams from .refusal_delta_block import RefusalDeltaBlock as RefusalDeltaBlock from .file_path_annotation import FilePathAnnotation as FilePathAnnotation from .image_url_delta_block import ImageURLDeltaBlock as ImageURLDeltaBlock from .message_content_delta import MessageContentDelta as MessageContentDelta from .message_create_params import MessageCreateParams as MessageCreateParams from .message_update_params import MessageUpdateParams as MessageUpdateParams from .refusal_content_block import RefusalContentBlock as RefusalContentBlock from .image_file_delta_block import ImageFileDeltaBlock as ImageFileDeltaBlock from .image_url_content_block import ImageURLContentBlock as ImageURLContentBlock from .file_citation_annotation import FileCitationAnnotation as FileCitationAnnotation from .image_file_content_block import ImageFileContentBlock as ImageFileContentBlock from .text_content_block_param import TextContentBlockParam as TextContentBlockParam from .file_path_delta_annotation import FilePathDeltaAnnotation as FilePathDeltaAnnotation from .message_content_part_param import MessageContentPartParam as MessageContentPartParam from .image_url_content_block_param import ImageURLContentBlockParam as ImageURLContentBlockParam from .file_citation_delta_annotation import FileCitationDeltaAnnotation as FileCitationDeltaAnnotation from .image_file_content_block_param import ImageFileContentBlockParam as ImageFileContentBlockParam from .run_submit_tool_outputs_params import RunSubmitToolOutputsParams as RunSubmitToolOutputsParams from .required_action_function_tool_call import RequiredActionFunctionToolCall as RequiredActionFunctionToolCall ================================================ FILE: src/openai/types/beta/threads/annotation.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from ...._utils import PropertyInfo from .file_path_annotation import FilePathAnnotation from .file_citation_annotation import FileCitationAnnotation __all__ = ["Annotation"] Annotation: TypeAlias = Annotated[Union[FileCitationAnnotation, FilePathAnnotation], PropertyInfo(discriminator="type")] ================================================ FILE: src/openai/types/beta/threads/annotation_delta.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from ...._utils import PropertyInfo from .file_path_delta_annotation import FilePathDeltaAnnotation from .file_citation_delta_annotation import FileCitationDeltaAnnotation __all__ = ["AnnotationDelta"] AnnotationDelta: TypeAlias = Annotated[ Union[FileCitationDeltaAnnotation, FilePathDeltaAnnotation], PropertyInfo(discriminator="type") ] ================================================ FILE: src/openai/types/beta/threads/file_citation_annotation.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["FileCitationAnnotation", "FileCitation"] class FileCitation(BaseModel): file_id: str """The ID of the specific File the citation is from.""" class FileCitationAnnotation(BaseModel): """ A citation within the message that points to a specific quote from a specific File associated with the assistant or the message. Generated when the assistant uses the "file_search" tool to search files. """ end_index: int file_citation: FileCitation start_index: int text: str """The text in the message content that needs to be replaced.""" type: Literal["file_citation"] """Always `file_citation`.""" ================================================ FILE: src/openai/types/beta/threads/file_citation_delta_annotation.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["FileCitationDeltaAnnotation", "FileCitation"] class FileCitation(BaseModel): file_id: Optional[str] = None """The ID of the specific File the citation is from.""" quote: Optional[str] = None """The specific quote in the file.""" class FileCitationDeltaAnnotation(BaseModel): """ A citation within the message that points to a specific quote from a specific File associated with the assistant or the message. Generated when the assistant uses the "file_search" tool to search files. """ index: int """The index of the annotation in the text content part.""" type: Literal["file_citation"] """Always `file_citation`.""" end_index: Optional[int] = None file_citation: Optional[FileCitation] = None start_index: Optional[int] = None text: Optional[str] = None """The text in the message content that needs to be replaced.""" ================================================ FILE: src/openai/types/beta/threads/file_path_annotation.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["FilePathAnnotation", "FilePath"] class FilePath(BaseModel): file_id: str """The ID of the file that was generated.""" class FilePathAnnotation(BaseModel): """ A URL for the file that's generated when the assistant used the `code_interpreter` tool to generate a file. """ end_index: int file_path: FilePath start_index: int text: str """The text in the message content that needs to be replaced.""" type: Literal["file_path"] """Always `file_path`.""" ================================================ FILE: src/openai/types/beta/threads/file_path_delta_annotation.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["FilePathDeltaAnnotation", "FilePath"] class FilePath(BaseModel): file_id: Optional[str] = None """The ID of the file that was generated.""" class FilePathDeltaAnnotation(BaseModel): """ A URL for the file that's generated when the assistant used the `code_interpreter` tool to generate a file. """ index: int """The index of the annotation in the text content part.""" type: Literal["file_path"] """Always `file_path`.""" end_index: Optional[int] = None file_path: Optional[FilePath] = None start_index: Optional[int] = None text: Optional[str] = None """The text in the message content that needs to be replaced.""" ================================================ FILE: src/openai/types/beta/threads/image_file.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ImageFile"] class ImageFile(BaseModel): file_id: str """ The [File](https://platform.openai.com/docs/api-reference/files) ID of the image in the message content. Set `purpose="vision"` when uploading the File if you need to later display the file content. """ detail: Optional[Literal["auto", "low", "high"]] = None """Specifies the detail level of the image if specified by the user. `low` uses fewer tokens, you can opt in to high resolution using `high`. """ ================================================ FILE: src/openai/types/beta/threads/image_file_content_block.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel from .image_file import ImageFile __all__ = ["ImageFileContentBlock"] class ImageFileContentBlock(BaseModel): """ References an image [File](https://platform.openai.com/docs/api-reference/files) in the content of a message. """ image_file: ImageFile type: Literal["image_file"] """Always `image_file`.""" ================================================ FILE: src/openai/types/beta/threads/image_file_content_block_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict from .image_file_param import ImageFileParam __all__ = ["ImageFileContentBlockParam"] class ImageFileContentBlockParam(TypedDict, total=False): """ References an image [File](https://platform.openai.com/docs/api-reference/files) in the content of a message. """ image_file: Required[ImageFileParam] type: Required[Literal["image_file"]] """Always `image_file`.""" ================================================ FILE: src/openai/types/beta/threads/image_file_delta.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ImageFileDelta"] class ImageFileDelta(BaseModel): detail: Optional[Literal["auto", "low", "high"]] = None """Specifies the detail level of the image if specified by the user. `low` uses fewer tokens, you can opt in to high resolution using `high`. """ file_id: Optional[str] = None """ The [File](https://platform.openai.com/docs/api-reference/files) ID of the image in the message content. Set `purpose="vision"` when uploading the File if you need to later display the file content. """ ================================================ FILE: src/openai/types/beta/threads/image_file_delta_block.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel from .image_file_delta import ImageFileDelta __all__ = ["ImageFileDeltaBlock"] class ImageFileDeltaBlock(BaseModel): """ References an image [File](https://platform.openai.com/docs/api-reference/files) in the content of a message. """ index: int """The index of the content part in the message.""" type: Literal["image_file"] """Always `image_file`.""" image_file: Optional[ImageFileDelta] = None ================================================ FILE: src/openai/types/beta/threads/image_file_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ImageFileParam"] class ImageFileParam(TypedDict, total=False): file_id: Required[str] """ The [File](https://platform.openai.com/docs/api-reference/files) ID of the image in the message content. Set `purpose="vision"` when uploading the File if you need to later display the file content. """ detail: Literal["auto", "low", "high"] """Specifies the detail level of the image if specified by the user. `low` uses fewer tokens, you can opt in to high resolution using `high`. """ ================================================ FILE: src/openai/types/beta/threads/image_url.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ImageURL"] class ImageURL(BaseModel): url: str """ The external URL of the image, must be a supported image types: jpeg, jpg, png, gif, webp. """ detail: Optional[Literal["auto", "low", "high"]] = None """Specifies the detail level of the image. `low` uses fewer tokens, you can opt in to high resolution using `high`. Default value is `auto` """ ================================================ FILE: src/openai/types/beta/threads/image_url_content_block.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .image_url import ImageURL from ...._models import BaseModel __all__ = ["ImageURLContentBlock"] class ImageURLContentBlock(BaseModel): """References an image URL in the content of a message.""" image_url: ImageURL type: Literal["image_url"] """The type of the content part.""" ================================================ FILE: src/openai/types/beta/threads/image_url_content_block_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict from .image_url_param import ImageURLParam __all__ = ["ImageURLContentBlockParam"] class ImageURLContentBlockParam(TypedDict, total=False): """References an image URL in the content of a message.""" image_url: Required[ImageURLParam] type: Required[Literal["image_url"]] """The type of the content part.""" ================================================ FILE: src/openai/types/beta/threads/image_url_delta.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["ImageURLDelta"] class ImageURLDelta(BaseModel): detail: Optional[Literal["auto", "low", "high"]] = None """Specifies the detail level of the image. `low` uses fewer tokens, you can opt in to high resolution using `high`. """ url: Optional[str] = None """ The URL of the image, must be a supported image types: jpeg, jpg, png, gif, webp. """ ================================================ FILE: src/openai/types/beta/threads/image_url_delta_block.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel from .image_url_delta import ImageURLDelta __all__ = ["ImageURLDeltaBlock"] class ImageURLDeltaBlock(BaseModel): """References an image URL in the content of a message.""" index: int """The index of the content part in the message.""" type: Literal["image_url"] """Always `image_url`.""" image_url: Optional[ImageURLDelta] = None ================================================ FILE: src/openai/types/beta/threads/image_url_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ImageURLParam"] class ImageURLParam(TypedDict, total=False): url: Required[str] """ The external URL of the image, must be a supported image types: jpeg, jpg, png, gif, webp. """ detail: Literal["auto", "low", "high"] """Specifies the detail level of the image. `low` uses fewer tokens, you can opt in to high resolution using `high`. Default value is `auto` """ ================================================ FILE: src/openai/types/beta/threads/message.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, TypeAlias from ...._models import BaseModel from .message_content import MessageContent from ...shared.metadata import Metadata from ..code_interpreter_tool import CodeInterpreterTool __all__ = [ "Message", "Attachment", "AttachmentTool", "AttachmentToolAssistantToolsFileSearchTypeOnly", "IncompleteDetails", ] class AttachmentToolAssistantToolsFileSearchTypeOnly(BaseModel): type: Literal["file_search"] """The type of tool being defined: `file_search`""" AttachmentTool: TypeAlias = Union[CodeInterpreterTool, AttachmentToolAssistantToolsFileSearchTypeOnly] class Attachment(BaseModel): file_id: Optional[str] = None """The ID of the file to attach to the message.""" tools: Optional[List[AttachmentTool]] = None """The tools to add this file to.""" class IncompleteDetails(BaseModel): """On an incomplete message, details about why the message is incomplete.""" reason: Literal["content_filter", "max_tokens", "run_cancelled", "run_expired", "run_failed"] """The reason the message is incomplete.""" class Message(BaseModel): """ Represents a message within a [thread](https://platform.openai.com/docs/api-reference/threads). """ id: str """The identifier, which can be referenced in API endpoints.""" assistant_id: Optional[str] = None """ If applicable, the ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) that authored this message. """ attachments: Optional[List[Attachment]] = None """A list of files attached to the message, and the tools they were added to.""" completed_at: Optional[int] = None """The Unix timestamp (in seconds) for when the message was completed.""" content: List[MessageContent] """The content of the message in array of text and/or images.""" created_at: int """The Unix timestamp (in seconds) for when the message was created.""" incomplete_at: Optional[int] = None """The Unix timestamp (in seconds) for when the message was marked as incomplete.""" incomplete_details: Optional[IncompleteDetails] = None """On an incomplete message, details about why the message is incomplete.""" metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ object: Literal["thread.message"] """The object type, which is always `thread.message`.""" role: Literal["user", "assistant"] """The entity that produced the message. One of `user` or `assistant`.""" run_id: Optional[str] = None """ The ID of the [run](https://platform.openai.com/docs/api-reference/runs) associated with the creation of this message. Value is `null` when messages are created manually using the create message or create thread endpoints. """ status: Literal["in_progress", "incomplete", "completed"] """ The status of the message, which can be either `in_progress`, `incomplete`, or `completed`. """ thread_id: str """ The [thread](https://platform.openai.com/docs/api-reference/threads) ID that this message belongs to. """ ================================================ FILE: src/openai/types/beta/threads/message_content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from ...._utils import PropertyInfo from .text_content_block import TextContentBlock from .refusal_content_block import RefusalContentBlock from .image_url_content_block import ImageURLContentBlock from .image_file_content_block import ImageFileContentBlock __all__ = ["MessageContent"] MessageContent: TypeAlias = Annotated[ Union[ImageFileContentBlock, ImageURLContentBlock, TextContentBlock, RefusalContentBlock], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/types/beta/threads/message_content_delta.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from ...._utils import PropertyInfo from .text_delta_block import TextDeltaBlock from .refusal_delta_block import RefusalDeltaBlock from .image_url_delta_block import ImageURLDeltaBlock from .image_file_delta_block import ImageFileDeltaBlock __all__ = ["MessageContentDelta"] MessageContentDelta: TypeAlias = Annotated[ Union[ImageFileDeltaBlock, TextDeltaBlock, RefusalDeltaBlock, ImageURLDeltaBlock], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/types/beta/threads/message_content_part_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import TypeAlias from .text_content_block_param import TextContentBlockParam from .image_url_content_block_param import ImageURLContentBlockParam from .image_file_content_block_param import ImageFileContentBlockParam __all__ = ["MessageContentPartParam"] MessageContentPartParam: TypeAlias = Union[ImageFileContentBlockParam, ImageURLContentBlockParam, TextContentBlockParam] ================================================ FILE: src/openai/types/beta/threads/message_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from ...shared_params.metadata import Metadata from .message_content_part_param import MessageContentPartParam from ..code_interpreter_tool_param import CodeInterpreterToolParam __all__ = ["MessageCreateParams", "Attachment", "AttachmentTool", "AttachmentToolFileSearch"] class MessageCreateParams(TypedDict, total=False): content: Required[Union[str, Iterable[MessageContentPartParam]]] """The text contents of the message.""" role: Required[Literal["user", "assistant"]] """The role of the entity that is creating the message. Allowed values include: - `user`: Indicates the message is sent by an actual user and should be used in most cases to represent user-generated messages. - `assistant`: Indicates the message is generated by the assistant. Use this value to insert messages from the assistant into the conversation. """ attachments: Optional[Iterable[Attachment]] """A list of files attached to the message, and the tools they should be added to.""" metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ class AttachmentToolFileSearch(TypedDict, total=False): type: Required[Literal["file_search"]] """The type of tool being defined: `file_search`""" AttachmentTool: TypeAlias = Union[CodeInterpreterToolParam, AttachmentToolFileSearch] class Attachment(TypedDict, total=False): file_id: str """The ID of the file to attach to the message.""" tools: Iterable[AttachmentTool] """The tools to add this file to.""" ================================================ FILE: src/openai/types/beta/threads/message_deleted.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["MessageDeleted"] class MessageDeleted(BaseModel): id: str deleted: bool object: Literal["thread.message.deleted"] ================================================ FILE: src/openai/types/beta/threads/message_delta.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ...._models import BaseModel from .message_content_delta import MessageContentDelta __all__ = ["MessageDelta"] class MessageDelta(BaseModel): """The delta containing the fields that have changed on the Message.""" content: Optional[List[MessageContentDelta]] = None """The content of the message in array of text and/or images.""" role: Optional[Literal["user", "assistant"]] = None """The entity that produced the message. One of `user` or `assistant`.""" ================================================ FILE: src/openai/types/beta/threads/message_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel from .message_delta import MessageDelta __all__ = ["MessageDeltaEvent"] class MessageDeltaEvent(BaseModel): """Represents a message delta i.e. any changed fields on a message during streaming. """ id: str """The identifier of the message, which can be referenced in API endpoints.""" delta: MessageDelta """The delta containing the fields that have changed on the Message.""" object: Literal["thread.message.delta"] """The object type, which is always `thread.message.delta`.""" ================================================ FILE: src/openai/types/beta/threads/message_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["MessageListParams"] class MessageListParams(TypedDict, total=False): after: str """A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. """ before: str """A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. """ limit: int """A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. """ order: Literal["asc", "desc"] """Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. """ run_id: str """Filter messages by the run ID that generated them.""" ================================================ FILE: src/openai/types/beta/threads/message_update_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Required, TypedDict from ...shared_params.metadata import Metadata __all__ = ["MessageUpdateParams"] class MessageUpdateParams(TypedDict, total=False): thread_id: Required[str] metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ ================================================ FILE: src/openai/types/beta/threads/refusal_content_block.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["RefusalContentBlock"] class RefusalContentBlock(BaseModel): """The refusal content generated by the assistant.""" refusal: str type: Literal["refusal"] """Always `refusal`.""" ================================================ FILE: src/openai/types/beta/threads/refusal_delta_block.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["RefusalDeltaBlock"] class RefusalDeltaBlock(BaseModel): """The refusal content that is part of a message.""" index: int """The index of the refusal part in the message.""" type: Literal["refusal"] """Always `refusal`.""" refusal: Optional[str] = None ================================================ FILE: src/openai/types/beta/threads/required_action_function_tool_call.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["RequiredActionFunctionToolCall", "Function"] class Function(BaseModel): """The function definition.""" arguments: str """The arguments that the model expects you to pass to the function.""" name: str """The name of the function.""" class RequiredActionFunctionToolCall(BaseModel): """Tool call objects""" id: str """The ID of the tool call. This ID must be referenced when you submit the tool outputs in using the [Submit tool outputs to run](https://platform.openai.com/docs/api-reference/runs/submitToolOutputs) endpoint. """ function: Function """The function definition.""" type: Literal["function"] """The type of tool call the output is required for. For now, this is always `function`. """ ================================================ FILE: src/openai/types/beta/threads/run.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ...._models import BaseModel from .run_status import RunStatus from ..assistant_tool import AssistantTool from ...shared.metadata import Metadata from ..assistant_tool_choice_option import AssistantToolChoiceOption from ..assistant_response_format_option import AssistantResponseFormatOption from .required_action_function_tool_call import RequiredActionFunctionToolCall __all__ = [ "Run", "IncompleteDetails", "LastError", "RequiredAction", "RequiredActionSubmitToolOutputs", "TruncationStrategy", "Usage", ] class IncompleteDetails(BaseModel): """Details on why the run is incomplete. Will be `null` if the run is not incomplete. """ reason: Optional[Literal["max_completion_tokens", "max_prompt_tokens"]] = None """The reason why the run is incomplete. This will point to which specific token limit was reached over the course of the run. """ class LastError(BaseModel): """The last error associated with this run. Will be `null` if there are no errors.""" code: Literal["server_error", "rate_limit_exceeded", "invalid_prompt"] """One of `server_error`, `rate_limit_exceeded`, or `invalid_prompt`.""" message: str """A human-readable description of the error.""" class RequiredActionSubmitToolOutputs(BaseModel): """Details on the tool outputs needed for this run to continue.""" tool_calls: List[RequiredActionFunctionToolCall] """A list of the relevant tool calls.""" class RequiredAction(BaseModel): """Details on the action required to continue the run. Will be `null` if no action is required. """ submit_tool_outputs: RequiredActionSubmitToolOutputs """Details on the tool outputs needed for this run to continue.""" type: Literal["submit_tool_outputs"] """For now, this is always `submit_tool_outputs`.""" class TruncationStrategy(BaseModel): """Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run. """ type: Literal["auto", "last_messages"] """The truncation strategy to use for the thread. The default is `auto`. If set to `last_messages`, the thread will be truncated to the n most recent messages in the thread. When set to `auto`, messages in the middle of the thread will be dropped to fit the context length of the model, `max_prompt_tokens`. """ last_messages: Optional[int] = None """ The number of most recent messages from the thread when constructing the context for the run. """ class Usage(BaseModel): """Usage statistics related to the run. This value will be `null` if the run is not in a terminal state (i.e. `in_progress`, `queued`, etc.). """ completion_tokens: int """Number of completion tokens used over the course of the run.""" prompt_tokens: int """Number of prompt tokens used over the course of the run.""" total_tokens: int """Total number of tokens used (prompt + completion).""" class Run(BaseModel): """ Represents an execution run on a [thread](https://platform.openai.com/docs/api-reference/threads). """ id: str """The identifier, which can be referenced in API endpoints.""" assistant_id: str """ The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) used for execution of this run. """ cancelled_at: Optional[int] = None """The Unix timestamp (in seconds) for when the run was cancelled.""" completed_at: Optional[int] = None """The Unix timestamp (in seconds) for when the run was completed.""" created_at: int """The Unix timestamp (in seconds) for when the run was created.""" expires_at: Optional[int] = None """The Unix timestamp (in seconds) for when the run will expire.""" failed_at: Optional[int] = None """The Unix timestamp (in seconds) for when the run failed.""" incomplete_details: Optional[IncompleteDetails] = None """Details on why the run is incomplete. Will be `null` if the run is not incomplete. """ instructions: str """ The instructions that the [assistant](https://platform.openai.com/docs/api-reference/assistants) used for this run. """ last_error: Optional[LastError] = None """The last error associated with this run. Will be `null` if there are no errors.""" max_completion_tokens: Optional[int] = None """ The maximum number of completion tokens specified to have been used over the course of the run. """ max_prompt_tokens: Optional[int] = None """ The maximum number of prompt tokens specified to have been used over the course of the run. """ metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ model: str """ The model that the [assistant](https://platform.openai.com/docs/api-reference/assistants) used for this run. """ object: Literal["thread.run"] """The object type, which is always `thread.run`.""" parallel_tool_calls: bool """ Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. """ required_action: Optional[RequiredAction] = None """Details on the action required to continue the run. Will be `null` if no action is required. """ response_format: Optional[AssistantResponseFormatOption] = None """Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. """ started_at: Optional[int] = None """The Unix timestamp (in seconds) for when the run was started.""" status: RunStatus """ The status of the run, which can be either `queued`, `in_progress`, `requires_action`, `cancelling`, `cancelled`, `failed`, `completed`, `incomplete`, or `expired`. """ thread_id: str """ The ID of the [thread](https://platform.openai.com/docs/api-reference/threads) that was executed on as a part of this run. """ tool_choice: Optional[AssistantToolChoiceOption] = None """ Controls which (if any) tool is called by the model. `none` means the model will not call any tools and instead generates a message. `auto` is the default value and means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools before responding to the user. Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. """ tools: List[AssistantTool] """ The list of tools that the [assistant](https://platform.openai.com/docs/api-reference/assistants) used for this run. """ truncation_strategy: Optional[TruncationStrategy] = None """Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run. """ usage: Optional[Usage] = None """Usage statistics related to the run. This value will be `null` if the run is not in a terminal state (i.e. `in_progress`, `queued`, etc.). """ temperature: Optional[float] = None """The sampling temperature used for this run. If not set, defaults to 1.""" top_p: Optional[float] = None """The nucleus sampling value used for this run. If not set, defaults to 1.""" ================================================ FILE: src/openai/types/beta/threads/run_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List, Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from ...shared.chat_model import ChatModel from ..assistant_tool_param import AssistantToolParam from .runs.run_step_include import RunStepInclude from ...shared_params.metadata import Metadata from ...shared.reasoning_effort import ReasoningEffort from .message_content_part_param import MessageContentPartParam from ..code_interpreter_tool_param import CodeInterpreterToolParam from ..assistant_tool_choice_option_param import AssistantToolChoiceOptionParam from ..assistant_response_format_option_param import AssistantResponseFormatOptionParam __all__ = [ "RunCreateParamsBase", "AdditionalMessage", "AdditionalMessageAttachment", "AdditionalMessageAttachmentTool", "AdditionalMessageAttachmentToolFileSearch", "TruncationStrategy", "RunCreateParamsNonStreaming", "RunCreateParamsStreaming", ] class RunCreateParamsBase(TypedDict, total=False): assistant_id: Required[str] """ The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to use to execute this run. """ include: List[RunStepInclude] """A list of additional fields to include in the response. Currently the only supported value is `step_details.tool_calls[*].file_search.results[*].content` to fetch the file search result content. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) for more information. """ additional_instructions: Optional[str] """Appends additional instructions at the end of the instructions for the run. This is useful for modifying the behavior on a per-run basis without overriding other instructions. """ additional_messages: Optional[Iterable[AdditionalMessage]] """Adds additional messages to the thread before creating the run.""" instructions: Optional[str] """ Overrides the [instructions](https://platform.openai.com/docs/api-reference/assistants/createAssistant) of the assistant. This is useful for modifying the behavior on a per-run basis. """ max_completion_tokens: Optional[int] """ The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. """ max_prompt_tokens: Optional[int] """The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info. """ metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ model: Union[str, ChatModel, None] """ The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used. """ parallel_tool_calls: bool """ Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. """ reasoning_effort: Optional[ReasoningEffort] """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ response_format: Optional[AssistantResponseFormatOptionParam] """Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the message the model generates is valid JSON. **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. """ temperature: Optional[float] """What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. """ tool_choice: Optional[AssistantToolChoiceOptionParam] """ Controls which (if any) tool is called by the model. `none` means the model will not call any tools and instead generates a message. `auto` is the default value and means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools before responding to the user. Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. """ tools: Optional[Iterable[AssistantToolParam]] """Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis. """ top_p: Optional[float] """ An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. """ truncation_strategy: Optional[TruncationStrategy] """Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run. """ class AdditionalMessageAttachmentToolFileSearch(TypedDict, total=False): type: Required[Literal["file_search"]] """The type of tool being defined: `file_search`""" AdditionalMessageAttachmentTool: TypeAlias = Union[CodeInterpreterToolParam, AdditionalMessageAttachmentToolFileSearch] class AdditionalMessageAttachment(TypedDict, total=False): file_id: str """The ID of the file to attach to the message.""" tools: Iterable[AdditionalMessageAttachmentTool] """The tools to add this file to.""" class AdditionalMessage(TypedDict, total=False): content: Required[Union[str, Iterable[MessageContentPartParam]]] """The text contents of the message.""" role: Required[Literal["user", "assistant"]] """The role of the entity that is creating the message. Allowed values include: - `user`: Indicates the message is sent by an actual user and should be used in most cases to represent user-generated messages. - `assistant`: Indicates the message is generated by the assistant. Use this value to insert messages from the assistant into the conversation. """ attachments: Optional[Iterable[AdditionalMessageAttachment]] """A list of files attached to the message, and the tools they should be added to.""" metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ class TruncationStrategy(TypedDict, total=False): """Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run. """ type: Required[Literal["auto", "last_messages"]] """The truncation strategy to use for the thread. The default is `auto`. If set to `last_messages`, the thread will be truncated to the n most recent messages in the thread. When set to `auto`, messages in the middle of the thread will be dropped to fit the context length of the model, `max_prompt_tokens`. """ last_messages: Optional[int] """ The number of most recent messages from the thread when constructing the context for the run. """ class RunCreateParamsNonStreaming(RunCreateParamsBase, total=False): stream: Optional[Literal[False]] """ If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. """ class RunCreateParamsStreaming(RunCreateParamsBase): stream: Required[Literal[True]] """ If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. """ RunCreateParams = Union[RunCreateParamsNonStreaming, RunCreateParamsStreaming] ================================================ FILE: src/openai/types/beta/threads/run_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["RunListParams"] class RunListParams(TypedDict, total=False): after: str """A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. """ before: str """A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. """ limit: int """A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. """ order: Literal["asc", "desc"] """Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. """ ================================================ FILE: src/openai/types/beta/threads/run_status.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["RunStatus"] RunStatus: TypeAlias = Literal[ "queued", "in_progress", "requires_action", "cancelling", "cancelled", "failed", "completed", "incomplete", "expired", ] ================================================ FILE: src/openai/types/beta/threads/run_submit_tool_outputs_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable, Optional from typing_extensions import Literal, Required, TypedDict __all__ = [ "RunSubmitToolOutputsParamsBase", "ToolOutput", "RunSubmitToolOutputsParamsNonStreaming", "RunSubmitToolOutputsParamsStreaming", ] class RunSubmitToolOutputsParamsBase(TypedDict, total=False): thread_id: Required[str] tool_outputs: Required[Iterable[ToolOutput]] """A list of tools for which the outputs are being submitted.""" class ToolOutput(TypedDict, total=False): output: str """The output of the tool call to be submitted to continue the run.""" tool_call_id: str """ The ID of the tool call in the `required_action` object within the run object the output is being submitted for. """ class RunSubmitToolOutputsParamsNonStreaming(RunSubmitToolOutputsParamsBase, total=False): stream: Optional[Literal[False]] """ If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. """ class RunSubmitToolOutputsParamsStreaming(RunSubmitToolOutputsParamsBase): stream: Required[Literal[True]] """ If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message. """ RunSubmitToolOutputsParams = Union[RunSubmitToolOutputsParamsNonStreaming, RunSubmitToolOutputsParamsStreaming] ================================================ FILE: src/openai/types/beta/threads/run_update_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Required, TypedDict from ...shared_params.metadata import Metadata __all__ = ["RunUpdateParams"] class RunUpdateParams(TypedDict, total=False): thread_id: Required[str] metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ ================================================ FILE: src/openai/types/beta/threads/runs/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .run_step import RunStep as RunStep from .tool_call import ToolCall as ToolCall from .run_step_delta import RunStepDelta as RunStepDelta from .tool_call_delta import ToolCallDelta as ToolCallDelta from .run_step_include import RunStepInclude as RunStepInclude from .step_list_params import StepListParams as StepListParams from .function_tool_call import FunctionToolCall as FunctionToolCall from .run_step_delta_event import RunStepDeltaEvent as RunStepDeltaEvent from .step_retrieve_params import StepRetrieveParams as StepRetrieveParams from .code_interpreter_logs import CodeInterpreterLogs as CodeInterpreterLogs from .file_search_tool_call import FileSearchToolCall as FileSearchToolCall from .tool_call_delta_object import ToolCallDeltaObject as ToolCallDeltaObject from .tool_calls_step_details import ToolCallsStepDetails as ToolCallsStepDetails from .function_tool_call_delta import FunctionToolCallDelta as FunctionToolCallDelta from .code_interpreter_tool_call import CodeInterpreterToolCall as CodeInterpreterToolCall from .file_search_tool_call_delta import FileSearchToolCallDelta as FileSearchToolCallDelta from .run_step_delta_message_delta import RunStepDeltaMessageDelta as RunStepDeltaMessageDelta from .code_interpreter_output_image import CodeInterpreterOutputImage as CodeInterpreterOutputImage from .message_creation_step_details import MessageCreationStepDetails as MessageCreationStepDetails from .code_interpreter_tool_call_delta import CodeInterpreterToolCallDelta as CodeInterpreterToolCallDelta ================================================ FILE: src/openai/types/beta/threads/runs/code_interpreter_logs.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ....._models import BaseModel __all__ = ["CodeInterpreterLogs"] class CodeInterpreterLogs(BaseModel): """Text output from the Code Interpreter tool call as part of a run step.""" index: int """The index of the output in the outputs array.""" type: Literal["logs"] """Always `logs`.""" logs: Optional[str] = None """The text output from the Code Interpreter tool call.""" ================================================ FILE: src/openai/types/beta/threads/runs/code_interpreter_output_image.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ....._models import BaseModel __all__ = ["CodeInterpreterOutputImage", "Image"] class Image(BaseModel): file_id: Optional[str] = None """ The [file](https://platform.openai.com/docs/api-reference/files) ID of the image. """ class CodeInterpreterOutputImage(BaseModel): index: int """The index of the output in the outputs array.""" type: Literal["image"] """Always `image`.""" image: Optional[Image] = None ================================================ FILE: src/openai/types/beta/threads/runs/code_interpreter_tool_call.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union from typing_extensions import Literal, Annotated, TypeAlias from ....._utils import PropertyInfo from ....._models import BaseModel __all__ = [ "CodeInterpreterToolCall", "CodeInterpreter", "CodeInterpreterOutput", "CodeInterpreterOutputLogs", "CodeInterpreterOutputImage", "CodeInterpreterOutputImageImage", ] class CodeInterpreterOutputLogs(BaseModel): """Text output from the Code Interpreter tool call as part of a run step.""" logs: str """The text output from the Code Interpreter tool call.""" type: Literal["logs"] """Always `logs`.""" class CodeInterpreterOutputImageImage(BaseModel): file_id: str """ The [file](https://platform.openai.com/docs/api-reference/files) ID of the image. """ class CodeInterpreterOutputImage(BaseModel): image: CodeInterpreterOutputImageImage type: Literal["image"] """Always `image`.""" CodeInterpreterOutput: TypeAlias = Annotated[ Union[CodeInterpreterOutputLogs, CodeInterpreterOutputImage], PropertyInfo(discriminator="type") ] class CodeInterpreter(BaseModel): """The Code Interpreter tool call definition.""" input: str """The input to the Code Interpreter tool call.""" outputs: List[CodeInterpreterOutput] """The outputs from the Code Interpreter tool call. Code Interpreter can output one or more items, including text (`logs`) or images (`image`). Each of these are represented by a different object type. """ class CodeInterpreterToolCall(BaseModel): """Details of the Code Interpreter tool call the run step was involved in.""" id: str """The ID of the tool call.""" code_interpreter: CodeInterpreter """The Code Interpreter tool call definition.""" type: Literal["code_interpreter"] """The type of tool call. This is always going to be `code_interpreter` for this type of tool call. """ ================================================ FILE: src/openai/types/beta/threads/runs/code_interpreter_tool_call_delta.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ....._utils import PropertyInfo from ....._models import BaseModel from .code_interpreter_logs import CodeInterpreterLogs from .code_interpreter_output_image import CodeInterpreterOutputImage __all__ = ["CodeInterpreterToolCallDelta", "CodeInterpreter", "CodeInterpreterOutput"] CodeInterpreterOutput: TypeAlias = Annotated[ Union[CodeInterpreterLogs, CodeInterpreterOutputImage], PropertyInfo(discriminator="type") ] class CodeInterpreter(BaseModel): """The Code Interpreter tool call definition.""" input: Optional[str] = None """The input to the Code Interpreter tool call.""" outputs: Optional[List[CodeInterpreterOutput]] = None """The outputs from the Code Interpreter tool call. Code Interpreter can output one or more items, including text (`logs`) or images (`image`). Each of these are represented by a different object type. """ class CodeInterpreterToolCallDelta(BaseModel): """Details of the Code Interpreter tool call the run step was involved in.""" index: int """The index of the tool call in the tool calls array.""" type: Literal["code_interpreter"] """The type of tool call. This is always going to be `code_interpreter` for this type of tool call. """ id: Optional[str] = None """The ID of the tool call.""" code_interpreter: Optional[CodeInterpreter] = None """The Code Interpreter tool call definition.""" ================================================ FILE: src/openai/types/beta/threads/runs/file_search_tool_call.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ....._models import BaseModel __all__ = [ "FileSearchToolCall", "FileSearch", "FileSearchRankingOptions", "FileSearchResult", "FileSearchResultContent", ] class FileSearchRankingOptions(BaseModel): """The ranking options for the file search.""" ranker: Literal["auto", "default_2024_08_21"] """The ranker to use for the file search. If not specified will use the `auto` ranker. """ score_threshold: float """The score threshold for the file search. All values must be a floating point number between 0 and 1. """ class FileSearchResultContent(BaseModel): text: Optional[str] = None """The text content of the file.""" type: Optional[Literal["text"]] = None """The type of the content.""" class FileSearchResult(BaseModel): """A result instance of the file search.""" file_id: str """The ID of the file that result was found in.""" file_name: str """The name of the file that result was found in.""" score: float """The score of the result. All values must be a floating point number between 0 and 1. """ content: Optional[List[FileSearchResultContent]] = None """The content of the result that was found. The content is only included if requested via the include query parameter. """ class FileSearch(BaseModel): """For now, this is always going to be an empty object.""" ranking_options: Optional[FileSearchRankingOptions] = None """The ranking options for the file search.""" results: Optional[List[FileSearchResult]] = None """The results of the file search.""" class FileSearchToolCall(BaseModel): id: str """The ID of the tool call object.""" file_search: FileSearch """For now, this is always going to be an empty object.""" type: Literal["file_search"] """The type of tool call. This is always going to be `file_search` for this type of tool call. """ ================================================ FILE: src/openai/types/beta/threads/runs/file_search_tool_call_delta.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ....._models import BaseModel __all__ = ["FileSearchToolCallDelta"] class FileSearchToolCallDelta(BaseModel): file_search: object """For now, this is always going to be an empty object.""" index: int """The index of the tool call in the tool calls array.""" type: Literal["file_search"] """The type of tool call. This is always going to be `file_search` for this type of tool call. """ id: Optional[str] = None """The ID of the tool call object.""" ================================================ FILE: src/openai/types/beta/threads/runs/function_tool_call.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ....._models import BaseModel __all__ = ["FunctionToolCall", "Function"] class Function(BaseModel): """The definition of the function that was called.""" arguments: str """The arguments passed to the function.""" name: str """The name of the function.""" output: Optional[str] = None """The output of the function. This will be `null` if the outputs have not been [submitted](https://platform.openai.com/docs/api-reference/runs/submitToolOutputs) yet. """ class FunctionToolCall(BaseModel): id: str """The ID of the tool call object.""" function: Function """The definition of the function that was called.""" type: Literal["function"] """The type of tool call. This is always going to be `function` for this type of tool call. """ ================================================ FILE: src/openai/types/beta/threads/runs/function_tool_call_delta.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ....._models import BaseModel __all__ = ["FunctionToolCallDelta", "Function"] class Function(BaseModel): """The definition of the function that was called.""" arguments: Optional[str] = None """The arguments passed to the function.""" name: Optional[str] = None """The name of the function.""" output: Optional[str] = None """The output of the function. This will be `null` if the outputs have not been [submitted](https://platform.openai.com/docs/api-reference/runs/submitToolOutputs) yet. """ class FunctionToolCallDelta(BaseModel): index: int """The index of the tool call in the tool calls array.""" type: Literal["function"] """The type of tool call. This is always going to be `function` for this type of tool call. """ id: Optional[str] = None """The ID of the tool call object.""" function: Optional[Function] = None """The definition of the function that was called.""" ================================================ FILE: src/openai/types/beta/threads/runs/message_creation_step_details.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ....._models import BaseModel __all__ = ["MessageCreationStepDetails", "MessageCreation"] class MessageCreation(BaseModel): message_id: str """The ID of the message that was created by this run step.""" class MessageCreationStepDetails(BaseModel): """Details of the message creation by the run step.""" message_creation: MessageCreation type: Literal["message_creation"] """Always `message_creation`.""" ================================================ FILE: src/openai/types/beta/threads/runs/run_step.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ....._utils import PropertyInfo from ....._models import BaseModel from ....shared.metadata import Metadata from .tool_calls_step_details import ToolCallsStepDetails from .message_creation_step_details import MessageCreationStepDetails __all__ = ["RunStep", "LastError", "StepDetails", "Usage"] class LastError(BaseModel): """The last error associated with this run step. Will be `null` if there are no errors. """ code: Literal["server_error", "rate_limit_exceeded"] """One of `server_error` or `rate_limit_exceeded`.""" message: str """A human-readable description of the error.""" StepDetails: TypeAlias = Annotated[ Union[MessageCreationStepDetails, ToolCallsStepDetails], PropertyInfo(discriminator="type") ] class Usage(BaseModel): """Usage statistics related to the run step. This value will be `null` while the run step's status is `in_progress`. """ completion_tokens: int """Number of completion tokens used over the course of the run step.""" prompt_tokens: int """Number of prompt tokens used over the course of the run step.""" total_tokens: int """Total number of tokens used (prompt + completion).""" class RunStep(BaseModel): """Represents a step in execution of a run.""" id: str """The identifier of the run step, which can be referenced in API endpoints.""" assistant_id: str """ The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) associated with the run step. """ cancelled_at: Optional[int] = None """The Unix timestamp (in seconds) for when the run step was cancelled.""" completed_at: Optional[int] = None """The Unix timestamp (in seconds) for when the run step completed.""" created_at: int """The Unix timestamp (in seconds) for when the run step was created.""" expired_at: Optional[int] = None """The Unix timestamp (in seconds) for when the run step expired. A step is considered expired if the parent run is expired. """ failed_at: Optional[int] = None """The Unix timestamp (in seconds) for when the run step failed.""" last_error: Optional[LastError] = None """The last error associated with this run step. Will be `null` if there are no errors. """ metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ object: Literal["thread.run.step"] """The object type, which is always `thread.run.step`.""" run_id: str """ The ID of the [run](https://platform.openai.com/docs/api-reference/runs) that this run step is a part of. """ status: Literal["in_progress", "cancelled", "failed", "completed", "expired"] """ The status of the run step, which can be either `in_progress`, `cancelled`, `failed`, `completed`, or `expired`. """ step_details: StepDetails """The details of the run step.""" thread_id: str """ The ID of the [thread](https://platform.openai.com/docs/api-reference/threads) that was run. """ type: Literal["message_creation", "tool_calls"] """The type of run step, which can be either `message_creation` or `tool_calls`.""" usage: Optional[Usage] = None """Usage statistics related to the run step. This value will be `null` while the run step's status is `in_progress`. """ ================================================ FILE: src/openai/types/beta/threads/runs/run_step_delta.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import Annotated, TypeAlias from ....._utils import PropertyInfo from ....._models import BaseModel from .tool_call_delta_object import ToolCallDeltaObject from .run_step_delta_message_delta import RunStepDeltaMessageDelta __all__ = ["RunStepDelta", "StepDetails"] StepDetails: TypeAlias = Annotated[ Union[RunStepDeltaMessageDelta, ToolCallDeltaObject], PropertyInfo(discriminator="type") ] class RunStepDelta(BaseModel): """The delta containing the fields that have changed on the run step.""" step_details: Optional[StepDetails] = None """The details of the run step.""" ================================================ FILE: src/openai/types/beta/threads/runs/run_step_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ....._models import BaseModel from .run_step_delta import RunStepDelta __all__ = ["RunStepDeltaEvent"] class RunStepDeltaEvent(BaseModel): """Represents a run step delta i.e. any changed fields on a run step during streaming. """ id: str """The identifier of the run step, which can be referenced in API endpoints.""" delta: RunStepDelta """The delta containing the fields that have changed on the run step.""" object: Literal["thread.run.step.delta"] """The object type, which is always `thread.run.step.delta`.""" ================================================ FILE: src/openai/types/beta/threads/runs/run_step_delta_message_delta.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ....._models import BaseModel __all__ = ["RunStepDeltaMessageDelta", "MessageCreation"] class MessageCreation(BaseModel): message_id: Optional[str] = None """The ID of the message that was created by this run step.""" class RunStepDeltaMessageDelta(BaseModel): """Details of the message creation by the run step.""" type: Literal["message_creation"] """Always `message_creation`.""" message_creation: Optional[MessageCreation] = None ================================================ FILE: src/openai/types/beta/threads/runs/run_step_include.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["RunStepInclude"] RunStepInclude: TypeAlias = Literal["step_details.tool_calls[*].file_search.results[*].content"] ================================================ FILE: src/openai/types/beta/threads/runs/step_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List from typing_extensions import Literal, Required, TypedDict from .run_step_include import RunStepInclude __all__ = ["StepListParams"] class StepListParams(TypedDict, total=False): thread_id: Required[str] after: str """A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. """ before: str """A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. """ include: List[RunStepInclude] """A list of additional fields to include in the response. Currently the only supported value is `step_details.tool_calls[*].file_search.results[*].content` to fetch the file search result content. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) for more information. """ limit: int """A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. """ order: Literal["asc", "desc"] """Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. """ ================================================ FILE: src/openai/types/beta/threads/runs/step_retrieve_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List from typing_extensions import Required, TypedDict from .run_step_include import RunStepInclude __all__ = ["StepRetrieveParams"] class StepRetrieveParams(TypedDict, total=False): thread_id: Required[str] run_id: Required[str] include: List[RunStepInclude] """A list of additional fields to include in the response. Currently the only supported value is `step_details.tool_calls[*].file_search.results[*].content` to fetch the file search result content. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) for more information. """ ================================================ FILE: src/openai/types/beta/threads/runs/tool_call.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from ....._utils import PropertyInfo from .function_tool_call import FunctionToolCall from .file_search_tool_call import FileSearchToolCall from .code_interpreter_tool_call import CodeInterpreterToolCall __all__ = ["ToolCall"] ToolCall: TypeAlias = Annotated[ Union[CodeInterpreterToolCall, FileSearchToolCall, FunctionToolCall], PropertyInfo(discriminator="type") ] ================================================ FILE: src/openai/types/beta/threads/runs/tool_call_delta.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from ....._utils import PropertyInfo from .function_tool_call_delta import FunctionToolCallDelta from .file_search_tool_call_delta import FileSearchToolCallDelta from .code_interpreter_tool_call_delta import CodeInterpreterToolCallDelta __all__ = ["ToolCallDelta"] ToolCallDelta: TypeAlias = Annotated[ Union[CodeInterpreterToolCallDelta, FileSearchToolCallDelta, FunctionToolCallDelta], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/types/beta/threads/runs/tool_call_delta_object.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ....._models import BaseModel from .tool_call_delta import ToolCallDelta __all__ = ["ToolCallDeltaObject"] class ToolCallDeltaObject(BaseModel): """Details of the tool call.""" type: Literal["tool_calls"] """Always `tool_calls`.""" tool_calls: Optional[List[ToolCallDelta]] = None """An array of tool calls the run step was involved in. These can be associated with one of three types of tools: `code_interpreter`, `file_search`, or `function`. """ ================================================ FILE: src/openai/types/beta/threads/runs/tool_calls_step_details.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List from typing_extensions import Literal from .tool_call import ToolCall from ....._models import BaseModel __all__ = ["ToolCallsStepDetails"] class ToolCallsStepDetails(BaseModel): """Details of the tool call.""" tool_calls: List[ToolCall] """An array of tool calls the run step was involved in. These can be associated with one of three types of tools: `code_interpreter`, `file_search`, or `function`. """ type: Literal["tool_calls"] """Always `tool_calls`.""" ================================================ FILE: src/openai/types/beta/threads/text.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List from ...._models import BaseModel from .annotation import Annotation __all__ = ["Text"] class Text(BaseModel): annotations: List[Annotation] value: str """The data that makes up the text.""" ================================================ FILE: src/openai/types/beta/threads/text_content_block.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .text import Text from ...._models import BaseModel __all__ = ["TextContentBlock"] class TextContentBlock(BaseModel): """The text content that is part of a message.""" text: Text type: Literal["text"] """Always `text`.""" ================================================ FILE: src/openai/types/beta/threads/text_content_block_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["TextContentBlockParam"] class TextContentBlockParam(TypedDict, total=False): """The text content that is part of a message.""" text: Required[str] """Text content to be sent to the model""" type: Required[Literal["text"]] """Always `text`.""" ================================================ FILE: src/openai/types/beta/threads/text_delta.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from ...._models import BaseModel from .annotation_delta import AnnotationDelta __all__ = ["TextDelta"] class TextDelta(BaseModel): annotations: Optional[List[AnnotationDelta]] = None value: Optional[str] = None """The data that makes up the text.""" ================================================ FILE: src/openai/types/beta/threads/text_delta_block.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel from .text_delta import TextDelta __all__ = ["TextDeltaBlock"] class TextDeltaBlock(BaseModel): """The text content that is part of a message.""" index: int """The index of the content part in the message.""" type: Literal["text"] """Always `text`.""" text: Optional[TextDelta] = None ================================================ FILE: src/openai/types/chat/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .chat_completion import ChatCompletion as ChatCompletion from .chat_completion_role import ChatCompletionRole as ChatCompletionRole from .chat_completion_audio import ChatCompletionAudio as ChatCompletionAudio from .chat_completion_chunk import ChatCompletionChunk as ChatCompletionChunk from .completion_list_params import CompletionListParams as CompletionListParams from .parsed_chat_completion import ( ParsedChoice as ParsedChoice, ParsedChatCompletion as ParsedChatCompletion, ParsedChatCompletionMessage as ParsedChatCompletionMessage, ) from .chat_completion_deleted import ChatCompletionDeleted as ChatCompletionDeleted from .chat_completion_message import ChatCompletionMessage as ChatCompletionMessage from .chat_completion_modality import ChatCompletionModality as ChatCompletionModality from .completion_create_params import CompletionCreateParams as CompletionCreateParams from .completion_update_params import CompletionUpdateParams as CompletionUpdateParams from .parsed_function_tool_call import ( ParsedFunction as ParsedFunction, ParsedFunctionToolCall as ParsedFunctionToolCall, ) from .chat_completion_tool_param import ChatCompletionToolParam as ChatCompletionToolParam from .chat_completion_audio_param import ChatCompletionAudioParam as ChatCompletionAudioParam from .chat_completion_function_tool import ChatCompletionFunctionTool as ChatCompletionFunctionTool from .chat_completion_message_param import ChatCompletionMessageParam as ChatCompletionMessageParam from .chat_completion_store_message import ChatCompletionStoreMessage as ChatCompletionStoreMessage from .chat_completion_token_logprob import ChatCompletionTokenLogprob as ChatCompletionTokenLogprob from .chat_completion_reasoning_effort import ChatCompletionReasoningEffort as ChatCompletionReasoningEffort from .chat_completion_tool_union_param import ChatCompletionToolUnionParam as ChatCompletionToolUnionParam from .chat_completion_content_part_text import ChatCompletionContentPartText as ChatCompletionContentPartText from .chat_completion_custom_tool_param import ChatCompletionCustomToolParam as ChatCompletionCustomToolParam from .chat_completion_message_tool_call import ( ChatCompletionMessageToolCall as ChatCompletionMessageToolCall, ChatCompletionMessageToolCallUnion as ChatCompletionMessageToolCallUnion, ) from .chat_completion_content_part_image import ChatCompletionContentPartImage as ChatCompletionContentPartImage from .chat_completion_content_part_param import ChatCompletionContentPartParam as ChatCompletionContentPartParam from .chat_completion_tool_message_param import ChatCompletionToolMessageParam as ChatCompletionToolMessageParam from .chat_completion_user_message_param import ChatCompletionUserMessageParam as ChatCompletionUserMessageParam from .chat_completion_allowed_tools_param import ChatCompletionAllowedToolsParam as ChatCompletionAllowedToolsParam from .chat_completion_function_tool_param import ChatCompletionFunctionToolParam as ChatCompletionFunctionToolParam from .chat_completion_stream_options_param import ChatCompletionStreamOptionsParam as ChatCompletionStreamOptionsParam from .chat_completion_system_message_param import ChatCompletionSystemMessageParam as ChatCompletionSystemMessageParam from .chat_completion_function_message_param import ( ChatCompletionFunctionMessageParam as ChatCompletionFunctionMessageParam, ) from .chat_completion_assistant_message_param import ( ChatCompletionAssistantMessageParam as ChatCompletionAssistantMessageParam, ) from .chat_completion_content_part_text_param import ( ChatCompletionContentPartTextParam as ChatCompletionContentPartTextParam, ) from .chat_completion_developer_message_param import ( ChatCompletionDeveloperMessageParam as ChatCompletionDeveloperMessageParam, ) from .chat_completion_message_tool_call_param import ( ChatCompletionMessageToolCallParam as ChatCompletionMessageToolCallParam, ) from .chat_completion_named_tool_choice_param import ( ChatCompletionNamedToolChoiceParam as ChatCompletionNamedToolChoiceParam, ) from .chat_completion_content_part_image_param import ( ChatCompletionContentPartImageParam as ChatCompletionContentPartImageParam, ) from .chat_completion_message_custom_tool_call import ( ChatCompletionMessageCustomToolCall as ChatCompletionMessageCustomToolCall, ) from .chat_completion_prediction_content_param import ( ChatCompletionPredictionContentParam as ChatCompletionPredictionContentParam, ) from .chat_completion_tool_choice_option_param import ( ChatCompletionToolChoiceOptionParam as ChatCompletionToolChoiceOptionParam, ) from .chat_completion_allowed_tool_choice_param import ( ChatCompletionAllowedToolChoiceParam as ChatCompletionAllowedToolChoiceParam, ) from .chat_completion_content_part_refusal_param import ( ChatCompletionContentPartRefusalParam as ChatCompletionContentPartRefusalParam, ) from .chat_completion_function_call_option_param import ( ChatCompletionFunctionCallOptionParam as ChatCompletionFunctionCallOptionParam, ) from .chat_completion_message_function_tool_call import ( ChatCompletionMessageFunctionToolCall as ChatCompletionMessageFunctionToolCall, ) from .chat_completion_message_tool_call_union_param import ( ChatCompletionMessageToolCallUnionParam as ChatCompletionMessageToolCallUnionParam, ) from .chat_completion_content_part_input_audio_param import ( ChatCompletionContentPartInputAudioParam as ChatCompletionContentPartInputAudioParam, ) from .chat_completion_message_custom_tool_call_param import ( ChatCompletionMessageCustomToolCallParam as ChatCompletionMessageCustomToolCallParam, ) from .chat_completion_named_tool_choice_custom_param import ( ChatCompletionNamedToolChoiceCustomParam as ChatCompletionNamedToolChoiceCustomParam, ) from .chat_completion_message_function_tool_call_param import ( ChatCompletionMessageFunctionToolCallParam as ChatCompletionMessageFunctionToolCallParam, ) ================================================ FILE: src/openai/types/chat/chat_completion.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel from ..completion_usage import CompletionUsage from .chat_completion_message import ChatCompletionMessage from .chat_completion_token_logprob import ChatCompletionTokenLogprob __all__ = ["ChatCompletion", "Choice", "ChoiceLogprobs"] class ChoiceLogprobs(BaseModel): """Log probability information for the choice.""" content: Optional[List[ChatCompletionTokenLogprob]] = None """A list of message content tokens with log probability information.""" refusal: Optional[List[ChatCompletionTokenLogprob]] = None """A list of message refusal tokens with log probability information.""" class Choice(BaseModel): finish_reason: Literal["stop", "length", "tool_calls", "content_filter", "function_call"] """The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence, `length` if the maximum number of tokens specified in the request was reached, `content_filter` if content was omitted due to a flag from our content filters, `tool_calls` if the model called a tool, or `function_call` (deprecated) if the model called a function. """ index: int """The index of the choice in the list of choices.""" logprobs: Optional[ChoiceLogprobs] = None """Log probability information for the choice.""" message: ChatCompletionMessage """A chat completion message generated by the model.""" class ChatCompletion(BaseModel): """ Represents a chat completion response returned by model, based on the provided input. """ id: str """A unique identifier for the chat completion.""" choices: List[Choice] """A list of chat completion choices. Can be more than one if `n` is greater than 1. """ created: int """The Unix timestamp (in seconds) of when the chat completion was created.""" model: str """The model used for the chat completion.""" object: Literal["chat.completion"] """The object type, which is always `chat.completion`.""" service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] = None """Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier. - When not set, the default behavior is 'auto'. When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. """ system_fingerprint: Optional[str] = None """This fingerprint represents the backend configuration that the model runs with. Can be used in conjunction with the `seed` request parameter to understand when backend changes have been made that might impact determinism. """ usage: Optional[CompletionUsage] = None """Usage statistics for the completion request.""" ================================================ FILE: src/openai/types/chat/chat_completion_allowed_tool_choice_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict from .chat_completion_allowed_tools_param import ChatCompletionAllowedToolsParam __all__ = ["ChatCompletionAllowedToolChoiceParam"] class ChatCompletionAllowedToolChoiceParam(TypedDict, total=False): """Constrains the tools available to the model to a pre-defined set.""" allowed_tools: Required[ChatCompletionAllowedToolsParam] """Constrains the tools available to the model to a pre-defined set.""" type: Required[Literal["allowed_tools"]] """Allowed tool configuration type. Always `allowed_tools`.""" ================================================ FILE: src/openai/types/chat/chat_completion_allowed_tools_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Iterable from typing_extensions import Literal, Required, TypedDict __all__ = ["ChatCompletionAllowedToolsParam"] class ChatCompletionAllowedToolsParam(TypedDict, total=False): """Constrains the tools available to the model to a pre-defined set.""" mode: Required[Literal["auto", "required"]] """Constrains the tools available to the model to a pre-defined set. `auto` allows the model to pick from among the allowed tools and generate a message. `required` requires the model to call one or more of the allowed tools. """ tools: Required[Iterable[Dict[str, object]]] """A list of tool definitions that the model should be allowed to call. For the Chat Completions API, the list of tool definitions might look like: ```json [ { "type": "function", "function": { "name": "get_weather" } }, { "type": "function", "function": { "name": "get_time" } } ] ``` """ ================================================ FILE: src/openai/types/chat/chat_completion_assistant_message_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from .chat_completion_content_part_text_param import ChatCompletionContentPartTextParam from .chat_completion_content_part_refusal_param import ChatCompletionContentPartRefusalParam from .chat_completion_message_tool_call_union_param import ChatCompletionMessageToolCallUnionParam __all__ = ["ChatCompletionAssistantMessageParam", "Audio", "ContentArrayOfContentPart", "FunctionCall"] class Audio(TypedDict, total=False): """ Data about a previous audio response from the model. [Learn more](https://platform.openai.com/docs/guides/audio). """ id: Required[str] """Unique identifier for a previous audio response from the model.""" ContentArrayOfContentPart: TypeAlias = Union[ChatCompletionContentPartTextParam, ChatCompletionContentPartRefusalParam] class FunctionCall(TypedDict, total=False): """Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model. """ arguments: Required[str] """ The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function. """ name: Required[str] """The name of the function to call.""" class ChatCompletionAssistantMessageParam(TypedDict, total=False): """Messages sent by the model in response to user messages.""" role: Required[Literal["assistant"]] """The role of the messages author, in this case `assistant`.""" audio: Optional[Audio] """ Data about a previous audio response from the model. [Learn more](https://platform.openai.com/docs/guides/audio). """ content: Union[str, Iterable[ContentArrayOfContentPart], None] """The contents of the assistant message. Required unless `tool_calls` or `function_call` is specified. """ function_call: Optional[FunctionCall] """Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model. """ name: str """An optional name for the participant. Provides the model information to differentiate between participants of the same role. """ refusal: Optional[str] """The refusal message by the assistant.""" tool_calls: Iterable[ChatCompletionMessageToolCallUnionParam] """The tool calls generated by the model, such as function calls.""" ================================================ FILE: src/openai/types/chat/chat_completion_audio.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from ..._models import BaseModel __all__ = ["ChatCompletionAudio"] class ChatCompletionAudio(BaseModel): """ If the audio output modality is requested, this object contains data about the audio response from the model. [Learn more](https://platform.openai.com/docs/guides/audio). """ id: str """Unique identifier for this audio response.""" data: str """ Base64 encoded audio bytes generated by the model, in the format specified in the request. """ expires_at: int """ The Unix timestamp (in seconds) for when this audio response will no longer be accessible on the server for use in multi-turn conversations. """ transcript: str """Transcript of the audio generated by the model.""" ================================================ FILE: src/openai/types/chat/chat_completion_audio_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, Required, TypeAlias, TypedDict __all__ = ["ChatCompletionAudioParam", "Voice", "VoiceID"] class VoiceID(TypedDict, total=False): """Custom voice reference.""" id: Required[str] """The custom voice ID, e.g. `voice_1234`.""" Voice: TypeAlias = Union[ str, Literal["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse", "marin", "cedar"], VoiceID ] class ChatCompletionAudioParam(TypedDict, total=False): """Parameters for audio output. Required when audio output is requested with `modalities: ["audio"]`. [Learn more](https://platform.openai.com/docs/guides/audio). """ format: Required[Literal["wav", "aac", "mp3", "flac", "opus", "pcm16"]] """Specifies the output audio format. Must be one of `wav`, `mp3`, `flac`, `opus`, or `pcm16`. """ voice: Required[Voice] """The voice the model uses to respond. Supported built-in voices are `alloy`, `ash`, `ballad`, `coral`, `echo`, `fable`, `nova`, `onyx`, `sage`, `shimmer`, `marin`, and `cedar`. You may also provide a custom voice object with an `id`, for example `{ "id": "voice_1234" }`. """ ================================================ FILE: src/openai/types/chat/chat_completion_chunk.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel from ..completion_usage import CompletionUsage from .chat_completion_token_logprob import ChatCompletionTokenLogprob __all__ = [ "ChatCompletionChunk", "Choice", "ChoiceDelta", "ChoiceDeltaFunctionCall", "ChoiceDeltaToolCall", "ChoiceDeltaToolCallFunction", "ChoiceLogprobs", ] class ChoiceDeltaFunctionCall(BaseModel): """Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model. """ arguments: Optional[str] = None """ The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function. """ name: Optional[str] = None """The name of the function to call.""" class ChoiceDeltaToolCallFunction(BaseModel): arguments: Optional[str] = None """ The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function. """ name: Optional[str] = None """The name of the function to call.""" class ChoiceDeltaToolCall(BaseModel): index: int id: Optional[str] = None """The ID of the tool call.""" function: Optional[ChoiceDeltaToolCallFunction] = None type: Optional[Literal["function"]] = None """The type of the tool. Currently, only `function` is supported.""" class ChoiceDelta(BaseModel): """A chat completion delta generated by streamed model responses.""" content: Optional[str] = None """The contents of the chunk message.""" function_call: Optional[ChoiceDeltaFunctionCall] = None """Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model. """ refusal: Optional[str] = None """The refusal message generated by the model.""" role: Optional[Literal["developer", "system", "user", "assistant", "tool"]] = None """The role of the author of this message.""" tool_calls: Optional[List[ChoiceDeltaToolCall]] = None class ChoiceLogprobs(BaseModel): """Log probability information for the choice.""" content: Optional[List[ChatCompletionTokenLogprob]] = None """A list of message content tokens with log probability information.""" refusal: Optional[List[ChatCompletionTokenLogprob]] = None """A list of message refusal tokens with log probability information.""" class Choice(BaseModel): delta: ChoiceDelta """A chat completion delta generated by streamed model responses.""" finish_reason: Optional[Literal["stop", "length", "tool_calls", "content_filter", "function_call"]] = None """The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence, `length` if the maximum number of tokens specified in the request was reached, `content_filter` if content was omitted due to a flag from our content filters, `tool_calls` if the model called a tool, or `function_call` (deprecated) if the model called a function. """ index: int """The index of the choice in the list of choices.""" logprobs: Optional[ChoiceLogprobs] = None """Log probability information for the choice.""" class ChatCompletionChunk(BaseModel): """ Represents a streamed chunk of a chat completion response returned by the model, based on the provided input. [Learn more](https://platform.openai.com/docs/guides/streaming-responses). """ id: str """A unique identifier for the chat completion. Each chunk has the same ID.""" choices: List[Choice] """A list of chat completion choices. Can contain more than one elements if `n` is greater than 1. Can also be empty for the last chunk if you set `stream_options: {"include_usage": true}`. """ created: int """The Unix timestamp (in seconds) of when the chat completion was created. Each chunk has the same timestamp. """ model: str """The model to generate the completion.""" object: Literal["chat.completion.chunk"] """The object type, which is always `chat.completion.chunk`.""" service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] = None """Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier. - When not set, the default behavior is 'auto'. When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. """ system_fingerprint: Optional[str] = None """ This fingerprint represents the backend configuration that the model runs with. Can be used in conjunction with the `seed` request parameter to understand when backend changes have been made that might impact determinism. """ usage: Optional[CompletionUsage] = None """ An optional field that will only be present when you set `stream_options: {"include_usage": true}` in your request. When present, it contains a null value **except for the last chunk** which contains the token usage statistics for the entire request. **NOTE:** If the stream is interrupted or cancelled, you may not receive the final usage chunk which contains the total token usage for the request. """ ================================================ FILE: src/openai/types/chat/chat_completion_content_part_image.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ChatCompletionContentPartImage", "ImageURL"] class ImageURL(BaseModel): url: str """Either a URL of the image or the base64 encoded image data.""" detail: Optional[Literal["auto", "low", "high"]] = None """Specifies the detail level of the image. Learn more in the [Vision guide](https://platform.openai.com/docs/guides/vision#low-or-high-fidelity-image-understanding). """ class ChatCompletionContentPartImage(BaseModel): """Learn about [image inputs](https://platform.openai.com/docs/guides/vision).""" image_url: ImageURL type: Literal["image_url"] """The type of the content part.""" ================================================ FILE: src/openai/types/chat/chat_completion_content_part_image_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ChatCompletionContentPartImageParam", "ImageURL"] class ImageURL(TypedDict, total=False): url: Required[str] """Either a URL of the image or the base64 encoded image data.""" detail: Literal["auto", "low", "high"] """Specifies the detail level of the image. Learn more in the [Vision guide](https://platform.openai.com/docs/guides/vision#low-or-high-fidelity-image-understanding). """ class ChatCompletionContentPartImageParam(TypedDict, total=False): """Learn about [image inputs](https://platform.openai.com/docs/guides/vision).""" image_url: Required[ImageURL] type: Required[Literal["image_url"]] """The type of the content part.""" ================================================ FILE: src/openai/types/chat/chat_completion_content_part_input_audio_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ChatCompletionContentPartInputAudioParam", "InputAudio"] class InputAudio(TypedDict, total=False): data: Required[str] """Base64 encoded audio data.""" format: Required[Literal["wav", "mp3"]] """The format of the encoded audio data. Currently supports "wav" and "mp3".""" class ChatCompletionContentPartInputAudioParam(TypedDict, total=False): """Learn about [audio inputs](https://platform.openai.com/docs/guides/audio).""" input_audio: Required[InputAudio] type: Required[Literal["input_audio"]] """The type of the content part. Always `input_audio`.""" ================================================ FILE: src/openai/types/chat/chat_completion_content_part_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, Required, TypeAlias, TypedDict from .chat_completion_content_part_text_param import ChatCompletionContentPartTextParam from .chat_completion_content_part_image_param import ChatCompletionContentPartImageParam from .chat_completion_content_part_input_audio_param import ChatCompletionContentPartInputAudioParam __all__ = ["ChatCompletionContentPartParam", "File", "FileFile"] class FileFile(TypedDict, total=False): file_data: str """ The base64 encoded file data, used when passing the file to the model as a string. """ file_id: str """The ID of an uploaded file to use as input.""" filename: str """The name of the file, used when passing the file to the model as a string.""" class File(TypedDict, total=False): """ Learn about [file inputs](https://platform.openai.com/docs/guides/text) for text generation. """ file: Required[FileFile] type: Required[Literal["file"]] """The type of the content part. Always `file`.""" ChatCompletionContentPartParam: TypeAlias = Union[ ChatCompletionContentPartTextParam, ChatCompletionContentPartImageParam, ChatCompletionContentPartInputAudioParam, File, ] ================================================ FILE: src/openai/types/chat/chat_completion_content_part_refusal_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ChatCompletionContentPartRefusalParam"] class ChatCompletionContentPartRefusalParam(TypedDict, total=False): refusal: Required[str] """The refusal message generated by the model.""" type: Required[Literal["refusal"]] """The type of the content part.""" ================================================ FILE: src/openai/types/chat/chat_completion_content_part_text.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ChatCompletionContentPartText"] class ChatCompletionContentPartText(BaseModel): """ Learn about [text inputs](https://platform.openai.com/docs/guides/text-generation). """ text: str """The text content.""" type: Literal["text"] """The type of the content part.""" ================================================ FILE: src/openai/types/chat/chat_completion_content_part_text_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ChatCompletionContentPartTextParam"] class ChatCompletionContentPartTextParam(TypedDict, total=False): """ Learn about [text inputs](https://platform.openai.com/docs/guides/text-generation). """ text: Required[str] """The text content.""" type: Required[Literal["text"]] """The type of the content part.""" ================================================ FILE: src/openai/types/chat/chat_completion_custom_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, Required, TypeAlias, TypedDict __all__ = [ "ChatCompletionCustomToolParam", "Custom", "CustomFormat", "CustomFormatText", "CustomFormatGrammar", "CustomFormatGrammarGrammar", ] class CustomFormatText(TypedDict, total=False): """Unconstrained free-form text.""" type: Required[Literal["text"]] """Unconstrained text format. Always `text`.""" class CustomFormatGrammarGrammar(TypedDict, total=False): """Your chosen grammar.""" definition: Required[str] """The grammar definition.""" syntax: Required[Literal["lark", "regex"]] """The syntax of the grammar definition. One of `lark` or `regex`.""" class CustomFormatGrammar(TypedDict, total=False): """A grammar defined by the user.""" grammar: Required[CustomFormatGrammarGrammar] """Your chosen grammar.""" type: Required[Literal["grammar"]] """Grammar format. Always `grammar`.""" CustomFormat: TypeAlias = Union[CustomFormatText, CustomFormatGrammar] class Custom(TypedDict, total=False): """Properties of the custom tool.""" name: Required[str] """The name of the custom tool, used to identify it in tool calls.""" description: str """Optional description of the custom tool, used to provide more context.""" format: CustomFormat """The input format for the custom tool. Default is unconstrained text.""" class ChatCompletionCustomToolParam(TypedDict, total=False): """A custom tool that processes input using a specified format.""" custom: Required[Custom] """Properties of the custom tool.""" type: Required[Literal["custom"]] """The type of the custom tool. Always `custom`.""" ================================================ FILE: src/openai/types/chat/chat_completion_deleted.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ChatCompletionDeleted"] class ChatCompletionDeleted(BaseModel): id: str """The ID of the chat completion that was deleted.""" deleted: bool """Whether the chat completion was deleted.""" object: Literal["chat.completion.deleted"] """The type of object being deleted.""" ================================================ FILE: src/openai/types/chat/chat_completion_developer_message_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable from typing_extensions import Literal, Required, TypedDict from .chat_completion_content_part_text_param import ChatCompletionContentPartTextParam __all__ = ["ChatCompletionDeveloperMessageParam"] class ChatCompletionDeveloperMessageParam(TypedDict, total=False): """ Developer-provided instructions that the model should follow, regardless of messages sent by the user. With o1 models and newer, `developer` messages replace the previous `system` messages. """ content: Required[Union[str, Iterable[ChatCompletionContentPartTextParam]]] """The contents of the developer message.""" role: Required[Literal["developer"]] """The role of the messages author, in this case `developer`.""" name: str """An optional name for the participant. Provides the model information to differentiate between participants of the same role. """ ================================================ FILE: src/openai/types/chat/chat_completion_function_call_option_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Required, TypedDict __all__ = ["ChatCompletionFunctionCallOptionParam"] class ChatCompletionFunctionCallOptionParam(TypedDict, total=False): """ Specifying a particular function via `{"name": "my_function"}` forces the model to call that function. """ name: Required[str] """The name of the function to call.""" ================================================ FILE: src/openai/types/chat/chat_completion_function_message_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Literal, Required, TypedDict __all__ = ["ChatCompletionFunctionMessageParam"] class ChatCompletionFunctionMessageParam(TypedDict, total=False): content: Required[Optional[str]] """The contents of the function message.""" name: Required[str] """The name of the function to call.""" role: Required[Literal["function"]] """The role of the messages author, in this case `function`.""" ================================================ FILE: src/openai/types/chat/chat_completion_function_tool.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel from ..shared.function_definition import FunctionDefinition __all__ = ["ChatCompletionFunctionTool"] class ChatCompletionFunctionTool(BaseModel): """A function tool that can be used to generate a response.""" function: FunctionDefinition type: Literal["function"] """The type of the tool. Currently, only `function` is supported.""" ================================================ FILE: src/openai/types/chat/chat_completion_function_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict from ..shared_params.function_definition import FunctionDefinition __all__ = ["ChatCompletionFunctionToolParam"] class ChatCompletionFunctionToolParam(TypedDict, total=False): """A function tool that can be used to generate a response.""" function: Required[FunctionDefinition] type: Required[Literal["function"]] """The type of the tool. Currently, only `function` is supported.""" ================================================ FILE: src/openai/types/chat/chat_completion_message.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel from .chat_completion_audio import ChatCompletionAudio from .chat_completion_message_tool_call import ChatCompletionMessageToolCallUnion __all__ = ["ChatCompletionMessage", "Annotation", "AnnotationURLCitation", "FunctionCall"] class AnnotationURLCitation(BaseModel): """A URL citation when using web search.""" end_index: int """The index of the last character of the URL citation in the message.""" start_index: int """The index of the first character of the URL citation in the message.""" title: str """The title of the web resource.""" url: str """The URL of the web resource.""" class Annotation(BaseModel): """A URL citation when using web search.""" type: Literal["url_citation"] """The type of the URL citation. Always `url_citation`.""" url_citation: AnnotationURLCitation """A URL citation when using web search.""" class FunctionCall(BaseModel): """Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model. """ arguments: str """ The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function. """ name: str """The name of the function to call.""" class ChatCompletionMessage(BaseModel): """A chat completion message generated by the model.""" content: Optional[str] = None """The contents of the message.""" refusal: Optional[str] = None """The refusal message generated by the model.""" role: Literal["assistant"] """The role of the author of this message.""" annotations: Optional[List[Annotation]] = None """ Annotations for the message, when applicable, as when using the [web search tool](https://platform.openai.com/docs/guides/tools-web-search?api-mode=chat). """ audio: Optional[ChatCompletionAudio] = None """ If the audio output modality is requested, this object contains data about the audio response from the model. [Learn more](https://platform.openai.com/docs/guides/audio). """ function_call: Optional[FunctionCall] = None """Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model. """ tool_calls: Optional[List[ChatCompletionMessageToolCallUnion]] = None """The tool calls generated by the model, such as function calls.""" ================================================ FILE: src/openai/types/chat/chat_completion_message_custom_tool_call.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ChatCompletionMessageCustomToolCall", "Custom"] class Custom(BaseModel): """The custom tool that the model called.""" input: str """The input for the custom tool call generated by the model.""" name: str """The name of the custom tool to call.""" class ChatCompletionMessageCustomToolCall(BaseModel): """A call to a custom tool created by the model.""" id: str """The ID of the tool call.""" custom: Custom """The custom tool that the model called.""" type: Literal["custom"] """The type of the tool. Always `custom`.""" ================================================ FILE: src/openai/types/chat/chat_completion_message_custom_tool_call_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ChatCompletionMessageCustomToolCallParam", "Custom"] class Custom(TypedDict, total=False): """The custom tool that the model called.""" input: Required[str] """The input for the custom tool call generated by the model.""" name: Required[str] """The name of the custom tool to call.""" class ChatCompletionMessageCustomToolCallParam(TypedDict, total=False): """A call to a custom tool created by the model.""" id: Required[str] """The ID of the tool call.""" custom: Required[Custom] """The custom tool that the model called.""" type: Required[Literal["custom"]] """The type of the tool. Always `custom`.""" ================================================ FILE: src/openai/types/chat/chat_completion_message_function_tool_call.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ChatCompletionMessageFunctionToolCall", "Function"] class Function(BaseModel): """The function that the model called.""" arguments: str """ The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function. """ name: str """The name of the function to call.""" class ChatCompletionMessageFunctionToolCall(BaseModel): """A call to a function tool created by the model.""" id: str """The ID of the tool call.""" function: Function """The function that the model called.""" type: Literal["function"] """The type of the tool. Currently, only `function` is supported.""" ================================================ FILE: src/openai/types/chat/chat_completion_message_function_tool_call_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ChatCompletionMessageFunctionToolCallParam", "Function"] class Function(TypedDict, total=False): """The function that the model called.""" arguments: Required[str] """ The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function. """ name: Required[str] """The name of the function to call.""" class ChatCompletionMessageFunctionToolCallParam(TypedDict, total=False): """A call to a function tool created by the model.""" id: Required[str] """The ID of the tool call.""" function: Required[Function] """The function that the model called.""" type: Required[Literal["function"]] """The type of the tool. Currently, only `function` is supported.""" ================================================ FILE: src/openai/types/chat/chat_completion_message_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import TypeAlias from .chat_completion_tool_message_param import ChatCompletionToolMessageParam from .chat_completion_user_message_param import ChatCompletionUserMessageParam from .chat_completion_system_message_param import ChatCompletionSystemMessageParam from .chat_completion_function_message_param import ChatCompletionFunctionMessageParam from .chat_completion_assistant_message_param import ChatCompletionAssistantMessageParam from .chat_completion_developer_message_param import ChatCompletionDeveloperMessageParam __all__ = ["ChatCompletionMessageParam"] ChatCompletionMessageParam: TypeAlias = Union[ ChatCompletionDeveloperMessageParam, ChatCompletionSystemMessageParam, ChatCompletionUserMessageParam, ChatCompletionAssistantMessageParam, ChatCompletionToolMessageParam, ChatCompletionFunctionMessageParam, ] ================================================ FILE: src/openai/types/chat/chat_completion_message_tool_call.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from ..._utils import PropertyInfo from .chat_completion_message_custom_tool_call import ChatCompletionMessageCustomToolCall from .chat_completion_message_function_tool_call import Function as Function, ChatCompletionMessageFunctionToolCall __all__ = ["Function", "ChatCompletionMessageToolCallUnion"] ChatCompletionMessageToolCallUnion: TypeAlias = Annotated[ Union[ChatCompletionMessageFunctionToolCall, ChatCompletionMessageCustomToolCall], PropertyInfo(discriminator="type"), ] ChatCompletionMessageToolCall: TypeAlias = ChatCompletionMessageFunctionToolCall ================================================ FILE: src/openai/types/chat/chat_completion_message_tool_call_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import TypeAlias from .chat_completion_message_function_tool_call_param import ( Function as Function, ChatCompletionMessageFunctionToolCallParam, ) __all__ = ["ChatCompletionMessageToolCallParam", "Function"] ChatCompletionMessageToolCallParam: TypeAlias = ChatCompletionMessageFunctionToolCallParam ================================================ FILE: src/openai/types/chat/chat_completion_message_tool_call_union_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import TypeAlias from .chat_completion_message_custom_tool_call_param import ChatCompletionMessageCustomToolCallParam from .chat_completion_message_function_tool_call_param import ChatCompletionMessageFunctionToolCallParam __all__ = ["ChatCompletionMessageToolCallUnionParam"] ChatCompletionMessageToolCallUnionParam: TypeAlias = Union[ ChatCompletionMessageFunctionToolCallParam, ChatCompletionMessageCustomToolCallParam ] ================================================ FILE: src/openai/types/chat/chat_completion_modality.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["ChatCompletionModality"] ChatCompletionModality: TypeAlias = Literal["text", "audio"] ================================================ FILE: src/openai/types/chat/chat_completion_named_tool_choice_custom_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ChatCompletionNamedToolChoiceCustomParam", "Custom"] class Custom(TypedDict, total=False): name: Required[str] """The name of the custom tool to call.""" class ChatCompletionNamedToolChoiceCustomParam(TypedDict, total=False): """Specifies a tool the model should use. Use to force the model to call a specific custom tool. """ custom: Required[Custom] type: Required[Literal["custom"]] """For custom tool calling, the type is always `custom`.""" ================================================ FILE: src/openai/types/chat/chat_completion_named_tool_choice_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ChatCompletionNamedToolChoiceParam", "Function"] class Function(TypedDict, total=False): name: Required[str] """The name of the function to call.""" class ChatCompletionNamedToolChoiceParam(TypedDict, total=False): """Specifies a tool the model should use. Use to force the model to call a specific function. """ function: Required[Function] type: Required[Literal["function"]] """For function calling, the type is always `function`.""" ================================================ FILE: src/openai/types/chat/chat_completion_prediction_content_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable from typing_extensions import Literal, Required, TypedDict from .chat_completion_content_part_text_param import ChatCompletionContentPartTextParam __all__ = ["ChatCompletionPredictionContentParam"] class ChatCompletionPredictionContentParam(TypedDict, total=False): """ Static predicted output content, such as the content of a text file that is being regenerated. """ content: Required[Union[str, Iterable[ChatCompletionContentPartTextParam]]] """ The content that should be matched when generating a model response. If generated tokens would match this content, the entire model response can be returned much more quickly. """ type: Required[Literal["content"]] """The type of the predicted content you want to provide. This type is currently always `content`. """ ================================================ FILE: src/openai/types/chat/chat_completion_reasoning_effort.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from ..shared.reasoning_effort import ReasoningEffort __all__ = ["ChatCompletionReasoningEffort"] ChatCompletionReasoningEffort = ReasoningEffort ================================================ FILE: src/openai/types/chat/chat_completion_role.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["ChatCompletionRole"] ChatCompletionRole: TypeAlias = Literal["developer", "system", "user", "assistant", "tool", "function"] ================================================ FILE: src/openai/types/chat/chat_completion_store_message.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import TypeAlias from .chat_completion_message import ChatCompletionMessage from .chat_completion_content_part_text import ChatCompletionContentPartText from .chat_completion_content_part_image import ChatCompletionContentPartImage __all__ = ["ChatCompletionStoreMessage", "ChatCompletionStoreMessageContentPart"] ChatCompletionStoreMessageContentPart: TypeAlias = Union[ChatCompletionContentPartText, ChatCompletionContentPartImage] class ChatCompletionStoreMessage(ChatCompletionMessage): """A chat completion message generated by the model.""" id: str """The identifier of the chat message.""" content_parts: Optional[List[ChatCompletionStoreMessageContentPart]] = None """ If a content parts array was provided, this is an array of `text` and `image_url` parts. Otherwise, null. """ ================================================ FILE: src/openai/types/chat/chat_completion_stream_options_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import TypedDict __all__ = ["ChatCompletionStreamOptionsParam"] class ChatCompletionStreamOptionsParam(TypedDict, total=False): """Options for streaming response. Only set this when you set `stream: true`.""" include_obfuscation: bool """When true, stream obfuscation will be enabled. Stream obfuscation adds random characters to an `obfuscation` field on streaming delta events to normalize payload sizes as a mitigation to certain side-channel attacks. These obfuscation fields are included by default, but add a small amount of overhead to the data stream. You can set `include_obfuscation` to false to optimize for bandwidth if you trust the network links between your application and the OpenAI API. """ include_usage: bool """If set, an additional chunk will be streamed before the `data: [DONE]` message. The `usage` field on this chunk shows the token usage statistics for the entire request, and the `choices` field will always be an empty array. All other chunks will also include a `usage` field, but with a null value. **NOTE:** If the stream is interrupted, you may not receive the final usage chunk which contains the total token usage for the request. """ ================================================ FILE: src/openai/types/chat/chat_completion_system_message_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable from typing_extensions import Literal, Required, TypedDict from .chat_completion_content_part_text_param import ChatCompletionContentPartTextParam __all__ = ["ChatCompletionSystemMessageParam"] class ChatCompletionSystemMessageParam(TypedDict, total=False): """ Developer-provided instructions that the model should follow, regardless of messages sent by the user. With o1 models and newer, use `developer` messages for this purpose instead. """ content: Required[Union[str, Iterable[ChatCompletionContentPartTextParam]]] """The contents of the system message.""" role: Required[Literal["system"]] """The role of the messages author, in this case `system`.""" name: str """An optional name for the participant. Provides the model information to differentiate between participants of the same role. """ ================================================ FILE: src/openai/types/chat/chat_completion_token_logprob.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from ..._models import BaseModel __all__ = ["ChatCompletionTokenLogprob", "TopLogprob"] class TopLogprob(BaseModel): token: str """The token.""" bytes: Optional[List[int]] = None """A list of integers representing the UTF-8 bytes representation of the token. Useful in instances where characters are represented by multiple tokens and their byte representations must be combined to generate the correct text representation. Can be `null` if there is no bytes representation for the token. """ logprob: float """The log probability of this token, if it is within the top 20 most likely tokens. Otherwise, the value `-9999.0` is used to signify that the token is very unlikely. """ class ChatCompletionTokenLogprob(BaseModel): token: str """The token.""" bytes: Optional[List[int]] = None """A list of integers representing the UTF-8 bytes representation of the token. Useful in instances where characters are represented by multiple tokens and their byte representations must be combined to generate the correct text representation. Can be `null` if there is no bytes representation for the token. """ logprob: float """The log probability of this token, if it is within the top 20 most likely tokens. Otherwise, the value `-9999.0` is used to signify that the token is very unlikely. """ top_logprobs: List[TopLogprob] """List of the most likely tokens and their log probability, at this token position. In rare cases, there may be fewer than the number of requested `top_logprobs` returned. """ ================================================ FILE: src/openai/types/chat/chat_completion_tool_choice_option_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, TypeAlias from .chat_completion_named_tool_choice_param import ChatCompletionNamedToolChoiceParam from .chat_completion_allowed_tool_choice_param import ChatCompletionAllowedToolChoiceParam from .chat_completion_named_tool_choice_custom_param import ChatCompletionNamedToolChoiceCustomParam __all__ = ["ChatCompletionToolChoiceOptionParam"] ChatCompletionToolChoiceOptionParam: TypeAlias = Union[ Literal["none", "auto", "required"], ChatCompletionAllowedToolChoiceParam, ChatCompletionNamedToolChoiceParam, ChatCompletionNamedToolChoiceCustomParam, ] ================================================ FILE: src/openai/types/chat/chat_completion_tool_message_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable from typing_extensions import Literal, Required, TypedDict from .chat_completion_content_part_text_param import ChatCompletionContentPartTextParam __all__ = ["ChatCompletionToolMessageParam"] class ChatCompletionToolMessageParam(TypedDict, total=False): content: Required[Union[str, Iterable[ChatCompletionContentPartTextParam]]] """The contents of the tool message.""" role: Required[Literal["tool"]] """The role of the messages author, in this case `tool`.""" tool_call_id: Required[str] """Tool call that this message is responding to.""" ================================================ FILE: src/openai/types/chat/chat_completion_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import TypeAlias from .chat_completion_function_tool_param import ( FunctionDefinition as FunctionDefinition, ChatCompletionFunctionToolParam, ) __all__ = ["ChatCompletionToolParam", "FunctionDefinition"] ChatCompletionToolParam: TypeAlias = ChatCompletionFunctionToolParam ================================================ FILE: src/openai/types/chat/chat_completion_tool_union_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import TypeAlias from .chat_completion_custom_tool_param import ChatCompletionCustomToolParam from .chat_completion_function_tool_param import ChatCompletionFunctionToolParam __all__ = ["ChatCompletionToolUnionParam"] ChatCompletionToolUnionParam: TypeAlias = Union[ChatCompletionFunctionToolParam, ChatCompletionCustomToolParam] ================================================ FILE: src/openai/types/chat/chat_completion_user_message_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable from typing_extensions import Literal, Required, TypedDict from .chat_completion_content_part_param import ChatCompletionContentPartParam __all__ = ["ChatCompletionUserMessageParam"] class ChatCompletionUserMessageParam(TypedDict, total=False): """ Messages sent by an end user, containing prompts or additional context information. """ content: Required[Union[str, Iterable[ChatCompletionContentPartParam]]] """The contents of the user message.""" role: Required[Literal["user"]] """The role of the messages author, in this case `user`.""" name: str """An optional name for the participant. Provides the model information to differentiate between participants of the same role. """ ================================================ FILE: src/openai/types/chat/completion_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, List, Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import SequenceNotStr from ..shared.chat_model import ChatModel from ..shared_params.metadata import Metadata from ..shared.reasoning_effort import ReasoningEffort from .chat_completion_audio_param import ChatCompletionAudioParam from .chat_completion_message_param import ChatCompletionMessageParam from .chat_completion_tool_union_param import ChatCompletionToolUnionParam from ..shared_params.function_parameters import FunctionParameters from ..shared_params.response_format_text import ResponseFormatText from .chat_completion_stream_options_param import ChatCompletionStreamOptionsParam from .chat_completion_prediction_content_param import ChatCompletionPredictionContentParam from .chat_completion_tool_choice_option_param import ChatCompletionToolChoiceOptionParam from ..shared_params.response_format_json_object import ResponseFormatJSONObject from ..shared_params.response_format_json_schema import ResponseFormatJSONSchema from .chat_completion_function_call_option_param import ChatCompletionFunctionCallOptionParam __all__ = [ "CompletionCreateParamsBase", "FunctionCall", "Function", "ResponseFormat", "WebSearchOptions", "WebSearchOptionsUserLocation", "WebSearchOptionsUserLocationApproximate", "CompletionCreateParamsNonStreaming", "CompletionCreateParamsStreaming", ] class CompletionCreateParamsBase(TypedDict, total=False): messages: Required[Iterable[ChatCompletionMessageParam]] """A list of messages comprising the conversation so far. Depending on the [model](https://platform.openai.com/docs/models) you use, different message types (modalities) are supported, like [text](https://platform.openai.com/docs/guides/text-generation), [images](https://platform.openai.com/docs/guides/vision), and [audio](https://platform.openai.com/docs/guides/audio). """ model: Required[Union[str, ChatModel]] """Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. """ audio: Optional[ChatCompletionAudioParam] """Parameters for audio output. Required when audio output is requested with `modalities: ["audio"]`. [Learn more](https://platform.openai.com/docs/guides/audio). """ frequency_penalty: Optional[float] """Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. """ function_call: FunctionCall """Deprecated in favor of `tool_choice`. Controls which (if any) function is called by the model. `none` means the model will not call a function and instead generates a message. `auto` means the model can pick between generating a message or calling a function. Specifying a particular function via `{"name": "my_function"}` forces the model to call that function. `none` is the default when no functions are present. `auto` is the default if functions are present. """ functions: Iterable[Function] """Deprecated in favor of `tools`. A list of functions the model may generate JSON inputs for. """ logit_bias: Optional[Dict[str, int]] """Modify the likelihood of specified tokens appearing in the completion. Accepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. """ logprobs: Optional[bool] """Whether to return log probabilities of the output tokens or not. If true, returns the log probabilities of each output token returned in the `content` of `message`. """ max_completion_tokens: Optional[int] """ An upper bound for the number of tokens that can be generated for a completion, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). """ max_tokens: Optional[int] """ The maximum number of [tokens](/tokenizer) that can be generated in the chat completion. This value can be used to control [costs](https://openai.com/api/pricing/) for text generated via API. This value is now deprecated in favor of `max_completion_tokens`, and is not compatible with [o-series models](https://platform.openai.com/docs/guides/reasoning). """ metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ modalities: Optional[List[Literal["text", "audio"]]] """ Output types that you would like the model to generate. Most models are capable of generating text, which is the default: `["text"]` The `gpt-4o-audio-preview` model can also be used to [generate audio](https://platform.openai.com/docs/guides/audio). To request that this model generate both text and audio responses, you can use: `["text", "audio"]` """ n: Optional[int] """How many chat completion choices to generate for each input message. Note that you will be charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to minimize costs. """ parallel_tool_calls: bool """ Whether to enable [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) during tool use. """ prediction: Optional[ChatCompletionPredictionContentParam] """ Static predicted output content, such as the content of a text file that is being regenerated. """ presence_penalty: Optional[float] """Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. """ prompt_cache_key: str """ Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://platform.openai.com/docs/guides/prompt-caching). """ prompt_cache_retention: Optional[Literal["in-memory", "24h"]] """The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). """ reasoning_effort: Optional[ReasoningEffort] """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ response_format: ResponseFormat """An object specifying the format that the model must output. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables the older JSON mode, which ensures the message the model generates is valid JSON. Using `json_schema` is preferred for models that support it. """ safety_identifier: str """ A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). """ seed: Optional[int] """ This feature is in Beta. If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result. Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend. """ service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] """Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier. - When not set, the default behavior is 'auto'. When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. """ stop: Union[Optional[str], SequenceNotStr[str], None] """Not supported with latest reasoning models `o3` and `o4-mini`. Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence. """ store: Optional[bool] """ Whether or not to store the output of this chat completion request for use in our [model distillation](https://platform.openai.com/docs/guides/distillation) or [evals](https://platform.openai.com/docs/guides/evals) products. Supports text and image inputs. Note: image inputs over 8MB will be dropped. """ stream_options: Optional[ChatCompletionStreamOptionsParam] """Options for streaming response. Only set this when you set `stream: true`.""" temperature: Optional[float] """What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. """ tool_choice: ChatCompletionToolChoiceOptionParam """ Controls which (if any) tool is called by the model. `none` means the model will not call any tool and instead generates a message. `auto` means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools. Specifying a particular tool via `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. `none` is the default when no tools are present. `auto` is the default if tools are present. """ tools: Iterable[ChatCompletionToolUnionParam] """A list of tools the model may call. You can provide either [custom tools](https://platform.openai.com/docs/guides/function-calling#custom-tools) or [function tools](https://platform.openai.com/docs/guides/function-calling). """ top_logprobs: Optional[int] """ An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. `logprobs` must be set to `true` if this parameter is used. """ top_p: Optional[float] """ An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. """ user: str """This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations. A stable identifier for your end-users. Used to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). """ verbosity: Optional[Literal["low", "medium", "high"]] """Constrains the verbosity of the model's response. Lower values will result in more concise responses, while higher values will result in more verbose responses. Currently supported values are `low`, `medium`, and `high`. """ web_search_options: WebSearchOptions """ This tool searches the web for relevant results to use in a response. Learn more about the [web search tool](https://platform.openai.com/docs/guides/tools-web-search?api-mode=chat). """ FunctionCall: TypeAlias = Union[Literal["none", "auto"], ChatCompletionFunctionCallOptionParam] class Function(TypedDict, total=False): name: Required[str] """The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64. """ description: str """ A description of what the function does, used by the model to choose when and how to call the function. """ parameters: FunctionParameters """The parameters the functions accepts, described as a JSON Schema object. See the [guide](https://platform.openai.com/docs/guides/function-calling) for examples, and the [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for documentation about the format. Omitting `parameters` defines a function with an empty parameter list. """ ResponseFormat: TypeAlias = Union[ResponseFormatText, ResponseFormatJSONSchema, ResponseFormatJSONObject] class WebSearchOptionsUserLocationApproximate(TypedDict, total=False): """Approximate location parameters for the search.""" city: str """Free text input for the city of the user, e.g. `San Francisco`.""" country: str """ The two-letter [ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1) of the user, e.g. `US`. """ region: str """Free text input for the region of the user, e.g. `California`.""" timezone: str """ The [IANA timezone](https://timeapi.io/documentation/iana-timezones) of the user, e.g. `America/Los_Angeles`. """ class WebSearchOptionsUserLocation(TypedDict, total=False): """Approximate location parameters for the search.""" approximate: Required[WebSearchOptionsUserLocationApproximate] """Approximate location parameters for the search.""" type: Required[Literal["approximate"]] """The type of location approximation. Always `approximate`.""" class WebSearchOptions(TypedDict, total=False): """ This tool searches the web for relevant results to use in a response. Learn more about the [web search tool](https://platform.openai.com/docs/guides/tools-web-search?api-mode=chat). """ search_context_size: Literal["low", "medium", "high"] """ High level guidance for the amount of context window space to use for the search. One of `low`, `medium`, or `high`. `medium` is the default. """ user_location: Optional[WebSearchOptionsUserLocation] """Approximate location parameters for the search.""" class CompletionCreateParamsNonStreaming(CompletionCreateParamsBase, total=False): stream: Optional[Literal[False]] """ If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/chat/streaming) for more information, along with the [streaming responses](https://platform.openai.com/docs/guides/streaming-responses) guide for more information on how to handle the streaming events. """ class CompletionCreateParamsStreaming(CompletionCreateParamsBase): stream: Required[Literal[True]] """ If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/chat/streaming) for more information, along with the [streaming responses](https://platform.openai.com/docs/guides/streaming-responses) guide for more information on how to handle the streaming events. """ CompletionCreateParams = Union[CompletionCreateParamsNonStreaming, CompletionCreateParamsStreaming] ================================================ FILE: src/openai/types/chat/completion_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Literal, TypedDict from ..shared_params.metadata import Metadata __all__ = ["CompletionListParams"] class CompletionListParams(TypedDict, total=False): after: str """Identifier for the last chat completion from the previous pagination request.""" limit: int """Number of Chat Completions to retrieve.""" metadata: Optional[Metadata] """A list of metadata keys to filter the Chat Completions by. Example: `metadata[key1]=value1&metadata[key2]=value2` """ model: str """The model used to generate the Chat Completions.""" order: Literal["asc", "desc"] """Sort order for Chat Completions by timestamp. Use `asc` for ascending order or `desc` for descending order. Defaults to `asc`. """ ================================================ FILE: src/openai/types/chat/completion_update_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Required, TypedDict from ..shared_params.metadata import Metadata __all__ = ["CompletionUpdateParams"] class CompletionUpdateParams(TypedDict, total=False): metadata: Required[Optional[Metadata]] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ ================================================ FILE: src/openai/types/chat/completions/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .message_list_params import MessageListParams as MessageListParams ================================================ FILE: src/openai/types/chat/completions/message_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["MessageListParams"] class MessageListParams(TypedDict, total=False): after: str """Identifier for the last message from the previous pagination request.""" limit: int """Number of messages to retrieve.""" order: Literal["asc", "desc"] """Sort order for messages by timestamp. Use `asc` for ascending order or `desc` for descending order. Defaults to `asc`. """ ================================================ FILE: src/openai/types/chat/parsed_chat_completion.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Generic, TypeVar, Optional from ..._models import GenericModel from .chat_completion import Choice, ChatCompletion from .chat_completion_message import ChatCompletionMessage from .parsed_function_tool_call import ParsedFunctionToolCall __all__ = ["ParsedChatCompletion", "ParsedChoice"] ContentType = TypeVar("ContentType") # we need to disable this check because we're overriding properties # with subclasses of their types which is technically unsound as # properties can be mutated. # pyright: reportIncompatibleVariableOverride=false class ParsedChatCompletionMessage(ChatCompletionMessage, GenericModel, Generic[ContentType]): parsed: Optional[ContentType] = None """The auto-parsed message contents""" tool_calls: Optional[List[ParsedFunctionToolCall]] = None # type: ignore[assignment] """The tool calls generated by the model, such as function calls.""" class ParsedChoice(Choice, GenericModel, Generic[ContentType]): message: ParsedChatCompletionMessage[ContentType] """A chat completion message generated by the model.""" class ParsedChatCompletion(ChatCompletion, GenericModel, Generic[ContentType]): choices: List[ParsedChoice[ContentType]] # type: ignore[assignment] """A list of chat completion choices. Can be more than one if `n` is greater than 1. """ ================================================ FILE: src/openai/types/chat/parsed_function_tool_call.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from .chat_completion_message_function_tool_call import Function, ChatCompletionMessageFunctionToolCall __all__ = ["ParsedFunctionToolCall", "ParsedFunction"] # we need to disable this check because we're overriding properties # with subclasses of their types which is technically unsound as # properties can be mutated. # pyright: reportIncompatibleVariableOverride=false class ParsedFunction(Function): parsed_arguments: Optional[object] = None """ The arguments to call the function with. If you used `openai.pydantic_function_tool()` then this will be an instance of the given `BaseModel`. Otherwise, this will be the parsed JSON arguments. """ class ParsedFunctionToolCall(ChatCompletionMessageFunctionToolCall): function: ParsedFunction """The function that the model called.""" ================================================ FILE: src/openai/types/chat_model.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .shared import chat_model __all__ = ["ChatModel"] ChatModel = chat_model.ChatModel ================================================ FILE: src/openai/types/completion.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from .._models import BaseModel from .completion_usage import CompletionUsage from .completion_choice import CompletionChoice __all__ = ["Completion"] class Completion(BaseModel): """Represents a completion response from the API. Note: both the streamed and non-streamed response objects share the same shape (unlike the chat endpoint). """ id: str """A unique identifier for the completion.""" choices: List[CompletionChoice] """The list of completion choices the model generated for the input prompt.""" created: int """The Unix timestamp (in seconds) of when the completion was created.""" model: str """The model used for completion.""" object: Literal["text_completion"] """The object type, which is always "text_completion" """ system_fingerprint: Optional[str] = None """This fingerprint represents the backend configuration that the model runs with. Can be used in conjunction with the `seed` request parameter to understand when backend changes have been made that might impact determinism. """ usage: Optional[CompletionUsage] = None """Usage statistics for the completion request.""" ================================================ FILE: src/openai/types/completion_choice.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Optional from typing_extensions import Literal from .._models import BaseModel __all__ = ["CompletionChoice", "Logprobs"] class Logprobs(BaseModel): text_offset: Optional[List[int]] = None token_logprobs: Optional[List[float]] = None tokens: Optional[List[str]] = None top_logprobs: Optional[List[Dict[str, float]]] = None class CompletionChoice(BaseModel): finish_reason: Literal["stop", "length", "content_filter"] """The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence, `length` if the maximum number of tokens specified in the request was reached, or `content_filter` if content was omitted due to a flag from our content filters. """ index: int logprobs: Optional[Logprobs] = None text: str ================================================ FILE: src/openai/types/completion_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Union, Iterable, Optional from typing_extensions import Literal, Required, TypedDict from .._types import SequenceNotStr from .chat.chat_completion_stream_options_param import ChatCompletionStreamOptionsParam __all__ = ["CompletionCreateParamsBase", "CompletionCreateParamsNonStreaming", "CompletionCreateParamsStreaming"] class CompletionCreateParamsBase(TypedDict, total=False): model: Required[Union[str, Literal["gpt-3.5-turbo-instruct", "davinci-002", "babbage-002"]]] """ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models) for descriptions of them. """ prompt: Required[Union[str, SequenceNotStr[str], Iterable[int], Iterable[Iterable[int]], None]] """ The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of token arrays. Note that <|endoftext|> is the document separator that the model sees during training, so if a prompt is not specified the model will generate as if from the beginning of a new document. """ best_of: Optional[int] """ Generates `best_of` completions server-side and returns the "best" (the one with the highest log probability per token). Results cannot be streamed. When used with `n`, `best_of` controls the number of candidate completions and `n` specifies how many to return – `best_of` must be greater than `n`. **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. """ echo: Optional[bool] """Echo back the prompt in addition to the completion""" frequency_penalty: Optional[float] """Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation) """ logit_bias: Optional[Dict[str, int]] """Modify the likelihood of specified tokens appearing in the completion. Accepts a JSON object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) to convert text to token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token from being generated. """ logprobs: Optional[int] """ Include the log probabilities on the `logprobs` most likely output tokens, as well the chosen tokens. For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` elements in the response. The maximum value for `logprobs` is 5. """ max_tokens: Optional[int] """ The maximum number of [tokens](/tokenizer) that can be generated in the completion. The token count of your prompt plus `max_tokens` cannot exceed the model's context length. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens. """ n: Optional[int] """How many completions to generate for each prompt. **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. """ presence_penalty: Optional[float] """Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation) """ seed: Optional[int] """ If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result. Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend. """ stop: Union[Optional[str], SequenceNotStr[str], None] """Not supported with latest reasoning models `o3` and `o4-mini`. Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence. """ stream_options: Optional[ChatCompletionStreamOptionsParam] """Options for streaming response. Only set this when you set `stream: true`.""" suffix: Optional[str] """The suffix that comes after a completion of inserted text. This parameter is only supported for `gpt-3.5-turbo-instruct`. """ temperature: Optional[float] """What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. """ top_p: Optional[float] """ An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. """ user: str """ A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). """ class CompletionCreateParamsNonStreaming(CompletionCreateParamsBase, total=False): stream: Optional[Literal[False]] """Whether to stream back partial progress. If set, tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message. [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). """ class CompletionCreateParamsStreaming(CompletionCreateParamsBase): stream: Required[Literal[True]] """Whether to stream back partial progress. If set, tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message. [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). """ CompletionCreateParams = Union[CompletionCreateParamsNonStreaming, CompletionCreateParamsStreaming] ================================================ FILE: src/openai/types/completion_usage.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from .._models import BaseModel __all__ = ["CompletionUsage", "CompletionTokensDetails", "PromptTokensDetails"] class CompletionTokensDetails(BaseModel): """Breakdown of tokens used in a completion.""" accepted_prediction_tokens: Optional[int] = None """ When using Predicted Outputs, the number of tokens in the prediction that appeared in the completion. """ audio_tokens: Optional[int] = None """Audio input tokens generated by the model.""" reasoning_tokens: Optional[int] = None """Tokens generated by the model for reasoning.""" rejected_prediction_tokens: Optional[int] = None """ When using Predicted Outputs, the number of tokens in the prediction that did not appear in the completion. However, like reasoning tokens, these tokens are still counted in the total completion tokens for purposes of billing, output, and context window limits. """ class PromptTokensDetails(BaseModel): """Breakdown of tokens used in the prompt.""" audio_tokens: Optional[int] = None """Audio input tokens present in the prompt.""" cached_tokens: Optional[int] = None """Cached tokens present in the prompt.""" class CompletionUsage(BaseModel): """Usage statistics for the completion request.""" completion_tokens: int """Number of tokens in the generated completion.""" prompt_tokens: int """Number of tokens in the prompt.""" total_tokens: int """Total number of tokens used in the request (prompt + completion).""" completion_tokens_details: Optional[CompletionTokensDetails] = None """Breakdown of tokens used in a completion.""" prompt_tokens_details: Optional[PromptTokensDetails] = None """Breakdown of tokens used in the prompt.""" ================================================ FILE: src/openai/types/container_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable from typing_extensions import Literal, Required, TypeAlias, TypedDict from .._types import SequenceNotStr from .responses.inline_skill_param import InlineSkillParam from .responses.skill_reference_param import SkillReferenceParam from .responses.container_network_policy_disabled_param import ContainerNetworkPolicyDisabledParam from .responses.container_network_policy_allowlist_param import ContainerNetworkPolicyAllowlistParam __all__ = ["ContainerCreateParams", "ExpiresAfter", "NetworkPolicy", "Skill"] class ContainerCreateParams(TypedDict, total=False): name: Required[str] """Name of the container to create.""" expires_after: ExpiresAfter """Container expiration time in seconds relative to the 'anchor' time.""" file_ids: SequenceNotStr[str] """IDs of files to copy to the container.""" memory_limit: Literal["1g", "4g", "16g", "64g"] """Optional memory limit for the container. Defaults to "1g".""" network_policy: NetworkPolicy """Network access policy for the container.""" skills: Iterable[Skill] """An optional list of skills referenced by id or inline data.""" class ExpiresAfter(TypedDict, total=False): """Container expiration time in seconds relative to the 'anchor' time.""" anchor: Required[Literal["last_active_at"]] """Time anchor for the expiration time. Currently only 'last_active_at' is supported. """ minutes: Required[int] NetworkPolicy: TypeAlias = Union[ContainerNetworkPolicyDisabledParam, ContainerNetworkPolicyAllowlistParam] Skill: TypeAlias = Union[SkillReferenceParam, InlineSkillParam] ================================================ FILE: src/openai/types/container_create_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from .._models import BaseModel __all__ = ["ContainerCreateResponse", "ExpiresAfter", "NetworkPolicy"] class ExpiresAfter(BaseModel): """ The container will expire after this time period. The anchor is the reference point for the expiration. The minutes is the number of minutes after the anchor before the container expires. """ anchor: Optional[Literal["last_active_at"]] = None """The reference point for the expiration.""" minutes: Optional[int] = None """The number of minutes after the anchor before the container expires.""" class NetworkPolicy(BaseModel): """Network access policy for the container.""" type: Literal["allowlist", "disabled"] """The network policy mode.""" allowed_domains: Optional[List[str]] = None """Allowed outbound domains when `type` is `allowlist`.""" class ContainerCreateResponse(BaseModel): id: str """Unique identifier for the container.""" created_at: int """Unix timestamp (in seconds) when the container was created.""" name: str """Name of the container.""" object: str """The type of this object.""" status: str """Status of the container (e.g., active, deleted).""" expires_after: Optional[ExpiresAfter] = None """ The container will expire after this time period. The anchor is the reference point for the expiration. The minutes is the number of minutes after the anchor before the container expires. """ last_active_at: Optional[int] = None """Unix timestamp (in seconds) when the container was last active.""" memory_limit: Optional[Literal["1g", "4g", "16g", "64g"]] = None """The memory limit configured for the container.""" network_policy: Optional[NetworkPolicy] = None """Network access policy for the container.""" ================================================ FILE: src/openai/types/container_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["ContainerListParams"] class ContainerListParams(TypedDict, total=False): after: str """A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. """ limit: int """A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. """ name: str """Filter results by container name.""" order: Literal["asc", "desc"] """Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. """ ================================================ FILE: src/openai/types/container_list_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from .._models import BaseModel __all__ = ["ContainerListResponse", "ExpiresAfter", "NetworkPolicy"] class ExpiresAfter(BaseModel): """ The container will expire after this time period. The anchor is the reference point for the expiration. The minutes is the number of minutes after the anchor before the container expires. """ anchor: Optional[Literal["last_active_at"]] = None """The reference point for the expiration.""" minutes: Optional[int] = None """The number of minutes after the anchor before the container expires.""" class NetworkPolicy(BaseModel): """Network access policy for the container.""" type: Literal["allowlist", "disabled"] """The network policy mode.""" allowed_domains: Optional[List[str]] = None """Allowed outbound domains when `type` is `allowlist`.""" class ContainerListResponse(BaseModel): id: str """Unique identifier for the container.""" created_at: int """Unix timestamp (in seconds) when the container was created.""" name: str """Name of the container.""" object: str """The type of this object.""" status: str """Status of the container (e.g., active, deleted).""" expires_after: Optional[ExpiresAfter] = None """ The container will expire after this time period. The anchor is the reference point for the expiration. The minutes is the number of minutes after the anchor before the container expires. """ last_active_at: Optional[int] = None """Unix timestamp (in seconds) when the container was last active.""" memory_limit: Optional[Literal["1g", "4g", "16g", "64g"]] = None """The memory limit configured for the container.""" network_policy: Optional[NetworkPolicy] = None """Network access policy for the container.""" ================================================ FILE: src/openai/types/container_retrieve_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from .._models import BaseModel __all__ = ["ContainerRetrieveResponse", "ExpiresAfter", "NetworkPolicy"] class ExpiresAfter(BaseModel): """ The container will expire after this time period. The anchor is the reference point for the expiration. The minutes is the number of minutes after the anchor before the container expires. """ anchor: Optional[Literal["last_active_at"]] = None """The reference point for the expiration.""" minutes: Optional[int] = None """The number of minutes after the anchor before the container expires.""" class NetworkPolicy(BaseModel): """Network access policy for the container.""" type: Literal["allowlist", "disabled"] """The network policy mode.""" allowed_domains: Optional[List[str]] = None """Allowed outbound domains when `type` is `allowlist`.""" class ContainerRetrieveResponse(BaseModel): id: str """Unique identifier for the container.""" created_at: int """Unix timestamp (in seconds) when the container was created.""" name: str """Name of the container.""" object: str """The type of this object.""" status: str """Status of the container (e.g., active, deleted).""" expires_after: Optional[ExpiresAfter] = None """ The container will expire after this time period. The anchor is the reference point for the expiration. The minutes is the number of minutes after the anchor before the container expires. """ last_active_at: Optional[int] = None """Unix timestamp (in seconds) when the container was last active.""" memory_limit: Optional[Literal["1g", "4g", "16g", "64g"]] = None """The memory limit configured for the container.""" network_policy: Optional[NetworkPolicy] = None """Network access policy for the container.""" ================================================ FILE: src/openai/types/containers/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .file_list_params import FileListParams as FileListParams from .file_create_params import FileCreateParams as FileCreateParams from .file_list_response import FileListResponse as FileListResponse from .file_create_response import FileCreateResponse as FileCreateResponse from .file_retrieve_response import FileRetrieveResponse as FileRetrieveResponse ================================================ FILE: src/openai/types/containers/file_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import TypedDict from ..._types import FileTypes __all__ = ["FileCreateParams"] class FileCreateParams(TypedDict, total=False): file: FileTypes """The File object (not file name) to be uploaded.""" file_id: str """Name of the file to create.""" ================================================ FILE: src/openai/types/containers/file_create_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["FileCreateResponse"] class FileCreateResponse(BaseModel): id: str """Unique identifier for the file.""" bytes: int """Size of the file in bytes.""" container_id: str """The container this file belongs to.""" created_at: int """Unix timestamp (in seconds) when the file was created.""" object: Literal["container.file"] """The type of this object (`container.file`).""" path: str """Path of the file in the container.""" source: str """Source of the file (e.g., `user`, `assistant`).""" ================================================ FILE: src/openai/types/containers/file_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["FileListParams"] class FileListParams(TypedDict, total=False): after: str """A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. """ limit: int """A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. """ order: Literal["asc", "desc"] """Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. """ ================================================ FILE: src/openai/types/containers/file_list_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["FileListResponse"] class FileListResponse(BaseModel): id: str """Unique identifier for the file.""" bytes: int """Size of the file in bytes.""" container_id: str """The container this file belongs to.""" created_at: int """Unix timestamp (in seconds) when the file was created.""" object: Literal["container.file"] """The type of this object (`container.file`).""" path: str """Path of the file in the container.""" source: str """Source of the file (e.g., `user`, `assistant`).""" ================================================ FILE: src/openai/types/containers/file_retrieve_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["FileRetrieveResponse"] class FileRetrieveResponse(BaseModel): id: str """Unique identifier for the file.""" bytes: int """Size of the file in bytes.""" container_id: str """The container this file belongs to.""" created_at: int """Unix timestamp (in seconds) when the file was created.""" object: Literal["container.file"] """The type of this object (`container.file`).""" path: str """Path of the file in the container.""" source: str """Source of the file (e.g., `user`, `assistant`).""" ================================================ FILE: src/openai/types/containers/files/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations ================================================ FILE: src/openai/types/conversations/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .message import Message as Message from .conversation import Conversation as Conversation from .text_content import TextContent as TextContent from .refusal_content import RefusalContent as RefusalContent from .item_list_params import ItemListParams as ItemListParams from .conversation_item import ConversationItem as ConversationItem from .input_file_content import InputFileContent as InputFileContent from .input_text_content import InputTextContent as InputTextContent from .item_create_params import ItemCreateParams as ItemCreateParams from .input_image_content import InputImageContent as InputImageContent from .output_text_content import OutputTextContent as OutputTextContent from .item_retrieve_params import ItemRetrieveParams as ItemRetrieveParams from .summary_text_content import SummaryTextContent as SummaryTextContent from .refusal_content_param import RefusalContentParam as RefusalContentParam from .conversation_item_list import ConversationItemList as ConversationItemList from .input_file_content_param import InputFileContentParam as InputFileContentParam from .input_text_content_param import InputTextContentParam as InputTextContentParam from .input_image_content_param import InputImageContentParam as InputImageContentParam from .output_text_content_param import OutputTextContentParam as OutputTextContentParam from .conversation_create_params import ConversationCreateParams as ConversationCreateParams from .conversation_update_params import ConversationUpdateParams as ConversationUpdateParams from .computer_screenshot_content import ComputerScreenshotContent as ComputerScreenshotContent from .conversation_deleted_resource import ConversationDeletedResource as ConversationDeletedResource ================================================ FILE: src/openai/types/conversations/computer_screenshot_content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ComputerScreenshotContent"] class ComputerScreenshotContent(BaseModel): """A screenshot of a computer.""" detail: Literal["low", "high", "auto", "original"] """The detail level of the screenshot image to be sent to the model. One of `high`, `low`, `auto`, or `original`. Defaults to `auto`. """ file_id: Optional[str] = None """The identifier of an uploaded file that contains the screenshot.""" image_url: Optional[str] = None """The URL of the screenshot image.""" type: Literal["computer_screenshot"] """Specifies the event type. For a computer screenshot, this property is always set to `computer_screenshot`. """ ================================================ FILE: src/openai/types/conversations/conversation.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["Conversation"] class Conversation(BaseModel): id: str """The unique ID of the conversation.""" created_at: int """ The time at which the conversation was created, measured in seconds since the Unix epoch. """ metadata: object """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ object: Literal["conversation"] """The object type, which is always `conversation`.""" ================================================ FILE: src/openai/types/conversations/conversation_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Iterable, Optional from typing_extensions import TypedDict from ..shared_params.metadata import Metadata from ..responses.response_input_item_param import ResponseInputItemParam __all__ = ["ConversationCreateParams"] class ConversationCreateParams(TypedDict, total=False): items: Optional[Iterable[ResponseInputItemParam]] """Initial items to include in the conversation context. You may add up to 20 items at a time. """ metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ ================================================ FILE: src/openai/types/conversations/conversation_deleted_resource.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ConversationDeletedResource"] class ConversationDeletedResource(BaseModel): id: str deleted: bool object: Literal["conversation.deleted"] ================================================ FILE: src/openai/types/conversations/conversation_item.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from .message import Message from ..._utils import PropertyInfo from ..._models import BaseModel from ..responses.response_reasoning_item import ResponseReasoningItem from ..responses.response_custom_tool_call import ResponseCustomToolCall from ..responses.response_tool_search_call import ResponseToolSearchCall from ..responses.response_computer_tool_call import ResponseComputerToolCall from ..responses.response_function_web_search import ResponseFunctionWebSearch from ..responses.response_apply_patch_tool_call import ResponseApplyPatchToolCall from ..responses.response_file_search_tool_call import ResponseFileSearchToolCall from ..responses.response_custom_tool_call_output import ResponseCustomToolCallOutput from ..responses.response_function_tool_call_item import ResponseFunctionToolCallItem from ..responses.response_tool_search_output_item import ResponseToolSearchOutputItem from ..responses.response_function_shell_tool_call import ResponseFunctionShellToolCall from ..responses.response_code_interpreter_tool_call import ResponseCodeInterpreterToolCall from ..responses.response_apply_patch_tool_call_output import ResponseApplyPatchToolCallOutput from ..responses.response_computer_tool_call_output_item import ResponseComputerToolCallOutputItem from ..responses.response_function_tool_call_output_item import ResponseFunctionToolCallOutputItem from ..responses.response_function_shell_tool_call_output import ResponseFunctionShellToolCallOutput __all__ = [ "ConversationItem", "ImageGenerationCall", "LocalShellCall", "LocalShellCallAction", "LocalShellCallOutput", "McpListTools", "McpListToolsTool", "McpApprovalRequest", "McpApprovalResponse", "McpCall", ] class ImageGenerationCall(BaseModel): """An image generation request made by the model.""" id: str """The unique ID of the image generation call.""" result: Optional[str] = None """The generated image encoded in base64.""" status: Literal["in_progress", "completed", "generating", "failed"] """The status of the image generation call.""" type: Literal["image_generation_call"] """The type of the image generation call. Always `image_generation_call`.""" class LocalShellCallAction(BaseModel): """Execute a shell command on the server.""" command: List[str] """The command to run.""" env: Dict[str, str] """Environment variables to set for the command.""" type: Literal["exec"] """The type of the local shell action. Always `exec`.""" timeout_ms: Optional[int] = None """Optional timeout in milliseconds for the command.""" user: Optional[str] = None """Optional user to run the command as.""" working_directory: Optional[str] = None """Optional working directory to run the command in.""" class LocalShellCall(BaseModel): """A tool call to run a command on the local shell.""" id: str """The unique ID of the local shell call.""" action: LocalShellCallAction """Execute a shell command on the server.""" call_id: str """The unique ID of the local shell tool call generated by the model.""" status: Literal["in_progress", "completed", "incomplete"] """The status of the local shell call.""" type: Literal["local_shell_call"] """The type of the local shell call. Always `local_shell_call`.""" class LocalShellCallOutput(BaseModel): """The output of a local shell tool call.""" id: str """The unique ID of the local shell tool call generated by the model.""" output: str """A JSON string of the output of the local shell tool call.""" type: Literal["local_shell_call_output"] """The type of the local shell tool call output. Always `local_shell_call_output`.""" status: Optional[Literal["in_progress", "completed", "incomplete"]] = None """The status of the item. One of `in_progress`, `completed`, or `incomplete`.""" class McpListToolsTool(BaseModel): """A tool available on an MCP server.""" input_schema: object """The JSON schema describing the tool's input.""" name: str """The name of the tool.""" annotations: Optional[object] = None """Additional annotations about the tool.""" description: Optional[str] = None """The description of the tool.""" class McpListTools(BaseModel): """A list of tools available on an MCP server.""" id: str """The unique ID of the list.""" server_label: str """The label of the MCP server.""" tools: List[McpListToolsTool] """The tools available on the server.""" type: Literal["mcp_list_tools"] """The type of the item. Always `mcp_list_tools`.""" error: Optional[str] = None """Error message if the server could not list tools.""" class McpApprovalRequest(BaseModel): """A request for human approval of a tool invocation.""" id: str """The unique ID of the approval request.""" arguments: str """A JSON string of arguments for the tool.""" name: str """The name of the tool to run.""" server_label: str """The label of the MCP server making the request.""" type: Literal["mcp_approval_request"] """The type of the item. Always `mcp_approval_request`.""" class McpApprovalResponse(BaseModel): """A response to an MCP approval request.""" id: str """The unique ID of the approval response""" approval_request_id: str """The ID of the approval request being answered.""" approve: bool """Whether the request was approved.""" type: Literal["mcp_approval_response"] """The type of the item. Always `mcp_approval_response`.""" reason: Optional[str] = None """Optional reason for the decision.""" class McpCall(BaseModel): """An invocation of a tool on an MCP server.""" id: str """The unique ID of the tool call.""" arguments: str """A JSON string of the arguments passed to the tool.""" name: str """The name of the tool that was run.""" server_label: str """The label of the MCP server running the tool.""" type: Literal["mcp_call"] """The type of the item. Always `mcp_call`.""" approval_request_id: Optional[str] = None """ Unique identifier for the MCP tool call approval request. Include this value in a subsequent `mcp_approval_response` input to approve or reject the corresponding tool call. """ error: Optional[str] = None """The error from the tool call, if any.""" output: Optional[str] = None """The output from the tool call.""" status: Optional[Literal["in_progress", "completed", "incomplete", "calling", "failed"]] = None """The status of the tool call. One of `in_progress`, `completed`, `incomplete`, `calling`, or `failed`. """ ConversationItem: TypeAlias = Annotated[ Union[ Message, ResponseFunctionToolCallItem, ResponseFunctionToolCallOutputItem, ResponseFileSearchToolCall, ResponseFunctionWebSearch, ImageGenerationCall, ResponseComputerToolCall, ResponseComputerToolCallOutputItem, ResponseToolSearchCall, ResponseToolSearchOutputItem, ResponseReasoningItem, ResponseCodeInterpreterToolCall, LocalShellCall, LocalShellCallOutput, ResponseFunctionShellToolCall, ResponseFunctionShellToolCallOutput, ResponseApplyPatchToolCall, ResponseApplyPatchToolCallOutput, McpListTools, McpApprovalRequest, McpApprovalResponse, McpCall, ResponseCustomToolCall, ResponseCustomToolCallOutput, ], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/types/conversations/conversation_item_list.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List from typing_extensions import Literal from ..._models import BaseModel from .conversation_item import ConversationItem __all__ = ["ConversationItemList"] class ConversationItemList(BaseModel): """A list of Conversation items.""" data: List[ConversationItem] """A list of conversation items.""" first_id: str """The ID of the first item in the list.""" has_more: bool """Whether there are more items available.""" last_id: str """The ID of the last item in the list.""" object: Literal["list"] """The type of object returned, must be `list`.""" ================================================ FILE: src/openai/types/conversations/conversation_update_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Required, TypedDict from ..shared_params.metadata import Metadata __all__ = ["ConversationUpdateParams"] class ConversationUpdateParams(TypedDict, total=False): metadata: Required[Optional[Metadata]] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ ================================================ FILE: src/openai/types/conversations/input_file_content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from ..responses.response_input_file import ResponseInputFile __all__ = ["InputFileContent"] InputFileContent = ResponseInputFile ================================================ FILE: src/openai/types/conversations/input_file_content_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from ..responses.response_input_file_param import ResponseInputFileParam InputFileContentParam = ResponseInputFileParam ================================================ FILE: src/openai/types/conversations/input_image_content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from ..responses.response_input_image import ResponseInputImage __all__ = ["InputImageContent"] InputImageContent = ResponseInputImage ================================================ FILE: src/openai/types/conversations/input_image_content_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from ..responses.response_input_image_param import ResponseInputImageParam InputImageContentParam = ResponseInputImageParam ================================================ FILE: src/openai/types/conversations/input_text_content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from ..responses.response_input_text import ResponseInputText __all__ = ["InputTextContent"] InputTextContent = ResponseInputText ================================================ FILE: src/openai/types/conversations/input_text_content_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from ..responses.response_input_text_param import ResponseInputTextParam InputTextContentParam = ResponseInputTextParam ================================================ FILE: src/openai/types/conversations/item_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List, Iterable from typing_extensions import Required, TypedDict from ..responses.response_includable import ResponseIncludable from ..responses.response_input_item_param import ResponseInputItemParam __all__ = ["ItemCreateParams"] class ItemCreateParams(TypedDict, total=False): items: Required[Iterable[ResponseInputItemParam]] """The items to add to the conversation. You may add up to 20 items at a time.""" include: List[ResponseIncludable] """Additional fields to include in the response. See the `include` parameter for [listing Conversation items above](https://platform.openai.com/docs/api-reference/conversations/list-items#conversations_list_items-include) for more information. """ ================================================ FILE: src/openai/types/conversations/item_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List from typing_extensions import Literal, TypedDict from ..responses.response_includable import ResponseIncludable __all__ = ["ItemListParams"] class ItemListParams(TypedDict, total=False): after: str """An item ID to list items after, used in pagination.""" include: List[ResponseIncludable] """Specify additional output data to include in the model response. Currently supported values are: - `web_search_call.action.sources`: Include the sources of the web search tool call. - `code_interpreter_call.outputs`: Includes the outputs of python code execution in code interpreter tool call items. - `computer_call_output.output.image_url`: Include image urls from the computer call output. - `file_search_call.results`: Include the search results of the file search tool call. - `message.input_image.image_url`: Include image urls from the input message. - `message.output_text.logprobs`: Include logprobs with assistant messages. - `reasoning.encrypted_content`: Includes an encrypted version of reasoning tokens in reasoning item outputs. This enables reasoning items to be used in multi-turn conversations when using the Responses API statelessly (like when the `store` parameter is set to `false`, or when an organization is enrolled in the zero data retention program). """ limit: int """A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. """ order: Literal["asc", "desc"] """The order to return the input items in. Default is `desc`. - `asc`: Return the input items in ascending order. - `desc`: Return the input items in descending order. """ ================================================ FILE: src/openai/types/conversations/item_retrieve_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List from typing_extensions import Required, TypedDict from ..responses.response_includable import ResponseIncludable __all__ = ["ItemRetrieveParams"] class ItemRetrieveParams(TypedDict, total=False): conversation_id: Required[str] include: List[ResponseIncludable] """Additional fields to include in the response. See the `include` parameter for [listing Conversation items above](https://platform.openai.com/docs/api-reference/conversations/list-items#conversations_list_items-include) for more information. """ ================================================ FILE: src/openai/types/conversations/message.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .text_content import TextContent from .summary_text_content import SummaryTextContent from .computer_screenshot_content import ComputerScreenshotContent from ..responses.response_input_file import ResponseInputFile from ..responses.response_input_text import ResponseInputText from ..responses.response_input_image import ResponseInputImage from ..responses.response_output_text import ResponseOutputText from ..responses.response_output_refusal import ResponseOutputRefusal __all__ = ["Message", "Content", "ContentReasoningText"] class ContentReasoningText(BaseModel): """Reasoning text from the model.""" text: str """The reasoning text from the model.""" type: Literal["reasoning_text"] """The type of the reasoning text. Always `reasoning_text`.""" Content: TypeAlias = Annotated[ Union[ ResponseInputText, ResponseOutputText, TextContent, SummaryTextContent, ContentReasoningText, ResponseOutputRefusal, ResponseInputImage, ComputerScreenshotContent, ResponseInputFile, ], PropertyInfo(discriminator="type"), ] class Message(BaseModel): """A message to or from the model.""" id: str """The unique ID of the message.""" content: List[Content] """The content of the message""" role: Literal["unknown", "user", "assistant", "system", "critic", "discriminator", "developer", "tool"] """The role of the message. One of `unknown`, `user`, `assistant`, `system`, `critic`, `discriminator`, `developer`, or `tool`. """ status: Literal["in_progress", "completed", "incomplete"] """The status of item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API. """ type: Literal["message"] """The type of the message. Always set to `message`.""" ================================================ FILE: src/openai/types/conversations/output_text_content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from ..responses.response_output_text import ResponseOutputText __all__ = ["OutputTextContent"] OutputTextContent = ResponseOutputText ================================================ FILE: src/openai/types/conversations/output_text_content_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from ..responses.response_output_text_param import ResponseOutputTextParam OutputTextContentParam = ResponseOutputTextParam ================================================ FILE: src/openai/types/conversations/refusal_content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from ..responses.response_output_refusal import ResponseOutputRefusal __all__ = ["RefusalContent"] RefusalContent = ResponseOutputRefusal ================================================ FILE: src/openai/types/conversations/refusal_content_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from ..responses.response_output_refusal_param import ResponseOutputRefusalParam RefusalContentParam = ResponseOutputRefusalParam ================================================ FILE: src/openai/types/conversations/summary_text_content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["SummaryTextContent"] class SummaryTextContent(BaseModel): """A summary text from the model.""" text: str """A summary of the reasoning output from the model so far.""" type: Literal["summary_text"] """The type of the object. Always `summary_text`.""" ================================================ FILE: src/openai/types/conversations/text_content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["TextContent"] class TextContent(BaseModel): """A text content.""" text: str type: Literal["text"] ================================================ FILE: src/openai/types/create_embedding_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List from typing_extensions import Literal from .._models import BaseModel from .embedding import Embedding __all__ = ["CreateEmbeddingResponse", "Usage"] class Usage(BaseModel): """The usage information for the request.""" prompt_tokens: int """The number of tokens used by the prompt.""" total_tokens: int """The total number of tokens used by the request.""" class CreateEmbeddingResponse(BaseModel): data: List[Embedding] """The list of embeddings generated by the model.""" model: str """The name of the model used to generate the embedding.""" object: Literal["list"] """The object type, which is always "list".""" usage: Usage """The usage information for the request.""" ================================================ FILE: src/openai/types/deleted_skill.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .._models import BaseModel __all__ = ["DeletedSkill"] class DeletedSkill(BaseModel): id: str deleted: bool object: Literal["skill.deleted"] ================================================ FILE: src/openai/types/embedding.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List from typing_extensions import Literal from .._models import BaseModel __all__ = ["Embedding"] class Embedding(BaseModel): """Represents an embedding vector returned by embedding endpoint.""" embedding: List[float] """The embedding vector, which is a list of floats. The length of vector depends on the model as listed in the [embedding guide](https://platform.openai.com/docs/guides/embeddings). """ index: int """The index of the embedding in the list of embeddings.""" object: Literal["embedding"] """The object type, which is always "embedding".""" ================================================ FILE: src/openai/types/embedding_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable from typing_extensions import Literal, Required, TypedDict from .._types import SequenceNotStr from .embedding_model import EmbeddingModel __all__ = ["EmbeddingCreateParams"] class EmbeddingCreateParams(TypedDict, total=False): input: Required[Union[str, SequenceNotStr[str], Iterable[int], Iterable[Iterable[int]]]] """Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a single request, pass an array of strings or array of token arrays. The input must not exceed the max input tokens for the model (8192 tokens for all embedding models), cannot be an empty string, and any array must be 2048 dimensions or less. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens. In addition to the per-input token limit, all embedding models enforce a maximum of 300,000 tokens summed across all inputs in a single request. """ model: Required[Union[str, EmbeddingModel]] """ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models) for descriptions of them. """ dimensions: int """The number of dimensions the resulting output embeddings should have. Only supported in `text-embedding-3` and later models. """ encoding_format: Literal["float", "base64"] """The format to return the embeddings in. Can be either `float` or [`base64`](https://pypi.org/project/pybase64/). """ user: str """ A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). """ ================================================ FILE: src/openai/types/embedding_model.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["EmbeddingModel"] EmbeddingModel: TypeAlias = Literal["text-embedding-ada-002", "text-embedding-3-small", "text-embedding-3-large"] ================================================ FILE: src/openai/types/eval_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from .._types import SequenceNotStr from .shared_params.metadata import Metadata from .graders.grader_inputs_param import GraderInputsParam from .graders.python_grader_param import PythonGraderParam from .graders.score_model_grader_param import ScoreModelGraderParam from .graders.string_check_grader_param import StringCheckGraderParam from .responses.response_input_text_param import ResponseInputTextParam from .graders.text_similarity_grader_param import TextSimilarityGraderParam from .responses.response_input_audio_param import ResponseInputAudioParam __all__ = [ "EvalCreateParams", "DataSourceConfig", "DataSourceConfigCustom", "DataSourceConfigLogs", "DataSourceConfigStoredCompletions", "TestingCriterion", "TestingCriterionLabelModel", "TestingCriterionLabelModelInput", "TestingCriterionLabelModelInputSimpleInputMessage", "TestingCriterionLabelModelInputEvalItem", "TestingCriterionLabelModelInputEvalItemContent", "TestingCriterionLabelModelInputEvalItemContentOutputText", "TestingCriterionLabelModelInputEvalItemContentInputImage", "TestingCriterionTextSimilarity", "TestingCriterionPython", "TestingCriterionScoreModel", ] class EvalCreateParams(TypedDict, total=False): data_source_config: Required[DataSourceConfig] """The configuration for the data source used for the evaluation runs. Dictates the schema of the data used in the evaluation. """ testing_criteria: Required[Iterable[TestingCriterion]] """A list of graders for all eval runs in this group. Graders can reference variables in the data source using double curly braces notation, like `{{item.variable_name}}`. To reference the model's output, use the `sample` namespace (ie, `{{sample.output_text}}`). """ metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ name: str """The name of the evaluation.""" class DataSourceConfigCustom(TypedDict, total=False): """ A CustomDataSourceConfig object that defines the schema for the data source used for the evaluation runs. This schema is used to define the shape of the data that will be: - Used to define your testing criteria and - What data is required when creating a run """ item_schema: Required[Dict[str, object]] """The json schema for each row in the data source.""" type: Required[Literal["custom"]] """The type of data source. Always `custom`.""" include_sample_schema: bool """ Whether the eval should expect you to populate the sample namespace (ie, by generating responses off of your data source) """ class DataSourceConfigLogs(TypedDict, total=False): """ A data source config which specifies the metadata property of your logs query. This is usually metadata like `usecase=chatbot` or `prompt-version=v2`, etc. """ type: Required[Literal["logs"]] """The type of data source. Always `logs`.""" metadata: Dict[str, object] """Metadata filters for the logs data source.""" class DataSourceConfigStoredCompletions(TypedDict, total=False): """Deprecated in favor of LogsDataSourceConfig.""" type: Required[Literal["stored_completions"]] """The type of data source. Always `stored_completions`.""" metadata: Dict[str, object] """Metadata filters for the stored completions data source.""" DataSourceConfig: TypeAlias = Union[DataSourceConfigCustom, DataSourceConfigLogs, DataSourceConfigStoredCompletions] class TestingCriterionLabelModelInputSimpleInputMessage(TypedDict, total=False): content: Required[str] """The content of the message.""" role: Required[str] """The role of the message (e.g. "system", "assistant", "user").""" class TestingCriterionLabelModelInputEvalItemContentOutputText(TypedDict, total=False): """A text output from the model.""" text: Required[str] """The text output from the model.""" type: Required[Literal["output_text"]] """The type of the output text. Always `output_text`.""" class TestingCriterionLabelModelInputEvalItemContentInputImage(TypedDict, total=False): """An image input block used within EvalItem content arrays.""" image_url: Required[str] """The URL of the image input.""" type: Required[Literal["input_image"]] """The type of the image input. Always `input_image`.""" detail: str """The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. Defaults to `auto`. """ TestingCriterionLabelModelInputEvalItemContent: TypeAlias = Union[ str, ResponseInputTextParam, TestingCriterionLabelModelInputEvalItemContentOutputText, TestingCriterionLabelModelInputEvalItemContentInputImage, ResponseInputAudioParam, GraderInputsParam, ] class TestingCriterionLabelModelInputEvalItem(TypedDict, total=False): """ A message input to the model with a role indicating instruction following hierarchy. Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role. Messages with the `assistant` role are presumed to have been generated by the model in previous interactions. """ content: Required[TestingCriterionLabelModelInputEvalItemContent] """Inputs to the model - can contain template strings. Supports text, output text, input images, and input audio, either as a single item or an array of items. """ role: Required[Literal["user", "assistant", "system", "developer"]] """The role of the message input. One of `user`, `assistant`, `system`, or `developer`. """ type: Literal["message"] """The type of the message input. Always `message`.""" TestingCriterionLabelModelInput: TypeAlias = Union[ TestingCriterionLabelModelInputSimpleInputMessage, TestingCriterionLabelModelInputEvalItem ] class TestingCriterionLabelModel(TypedDict, total=False): """ A LabelModelGrader object which uses a model to assign labels to each item in the evaluation. """ input: Required[Iterable[TestingCriterionLabelModelInput]] """A list of chat messages forming the prompt or context. May include variable references to the `item` namespace, ie {{item.name}}. """ labels: Required[SequenceNotStr[str]] """The labels to classify to each item in the evaluation.""" model: Required[str] """The model to use for the evaluation. Must support structured outputs.""" name: Required[str] """The name of the grader.""" passing_labels: Required[SequenceNotStr[str]] """The labels that indicate a passing result. Must be a subset of labels.""" type: Required[Literal["label_model"]] """The object type, which is always `label_model`.""" class TestingCriterionTextSimilarity(TextSimilarityGraderParam, total=False): """A TextSimilarityGrader object which grades text based on similarity metrics.""" pass_threshold: Required[float] """The threshold for the score.""" class TestingCriterionPython(PythonGraderParam, total=False): """A PythonGrader object that runs a python script on the input.""" pass_threshold: float """The threshold for the score.""" class TestingCriterionScoreModel(ScoreModelGraderParam, total=False): """A ScoreModelGrader object that uses a model to assign a score to the input.""" pass_threshold: float """The threshold for the score.""" TestingCriterion: TypeAlias = Union[ TestingCriterionLabelModel, StringCheckGraderParam, TestingCriterionTextSimilarity, TestingCriterionPython, TestingCriterionScoreModel, ] ================================================ FILE: src/openai/types/eval_create_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo from .._utils import PropertyInfo from .._models import BaseModel from .shared.metadata import Metadata from .graders.python_grader import PythonGrader from .graders.label_model_grader import LabelModelGrader from .graders.score_model_grader import ScoreModelGrader from .graders.string_check_grader import StringCheckGrader from .eval_custom_data_source_config import EvalCustomDataSourceConfig from .graders.text_similarity_grader import TextSimilarityGrader from .eval_stored_completions_data_source_config import EvalStoredCompletionsDataSourceConfig __all__ = [ "EvalCreateResponse", "DataSourceConfig", "DataSourceConfigLogs", "TestingCriterion", "TestingCriterionEvalGraderTextSimilarity", "TestingCriterionEvalGraderPython", "TestingCriterionEvalGraderScoreModel", ] class DataSourceConfigLogs(BaseModel): """ A LogsDataSourceConfig which specifies the metadata property of your logs query. This is usually metadata like `usecase=chatbot` or `prompt-version=v2`, etc. The schema returned by this data source config is used to defined what variables are available in your evals. `item` and `sample` are both defined when using this data source config. """ schema_: Dict[str, object] = FieldInfo(alias="schema") """ The json schema for the run data source items. Learn how to build JSON schemas [here](https://json-schema.org/). """ type: Literal["logs"] """The type of data source. Always `logs`.""" metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ DataSourceConfig: TypeAlias = Annotated[ Union[EvalCustomDataSourceConfig, DataSourceConfigLogs, EvalStoredCompletionsDataSourceConfig], PropertyInfo(discriminator="type"), ] class TestingCriterionEvalGraderTextSimilarity(TextSimilarityGrader): __test__ = False """A TextSimilarityGrader object which grades text based on similarity metrics.""" pass_threshold: float """The threshold for the score.""" class TestingCriterionEvalGraderPython(PythonGrader): __test__ = False """A PythonGrader object that runs a python script on the input.""" pass_threshold: Optional[float] = None """The threshold for the score.""" class TestingCriterionEvalGraderScoreModel(ScoreModelGrader): __test__ = False """A ScoreModelGrader object that uses a model to assign a score to the input.""" pass_threshold: Optional[float] = None """The threshold for the score.""" TestingCriterion: TypeAlias = Union[ LabelModelGrader, StringCheckGrader, TestingCriterionEvalGraderTextSimilarity, TestingCriterionEvalGraderPython, TestingCriterionEvalGraderScoreModel, ] class EvalCreateResponse(BaseModel): """ An Eval object with a data source config and testing criteria. An Eval represents a task to be done for your LLM integration. Like: - Improve the quality of my chatbot - See how well my chatbot handles customer support - Check if o4-mini is better at my usecase than gpt-4o """ id: str """Unique identifier for the evaluation.""" created_at: int """The Unix timestamp (in seconds) for when the eval was created.""" data_source_config: DataSourceConfig """Configuration of data sources used in runs of the evaluation.""" metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ name: str """The name of the evaluation.""" object: Literal["eval"] """The object type.""" testing_criteria: List[TestingCriterion] """A list of testing criteria.""" ================================================ FILE: src/openai/types/eval_custom_data_source_config.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict from typing_extensions import Literal from pydantic import Field as FieldInfo from .._models import BaseModel __all__ = ["EvalCustomDataSourceConfig"] class EvalCustomDataSourceConfig(BaseModel): """ A CustomDataSourceConfig which specifies the schema of your `item` and optionally `sample` namespaces. The response schema defines the shape of the data that will be: - Used to define your testing criteria and - What data is required when creating a run """ schema_: Dict[str, object] = FieldInfo(alias="schema") """ The json schema for the run data source items. Learn how to build JSON schemas [here](https://json-schema.org/). """ type: Literal["custom"] """The type of data source. Always `custom`.""" ================================================ FILE: src/openai/types/eval_delete_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .._models import BaseModel __all__ = ["EvalDeleteResponse"] class EvalDeleteResponse(BaseModel): deleted: bool eval_id: str object: str ================================================ FILE: src/openai/types/eval_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["EvalListParams"] class EvalListParams(TypedDict, total=False): after: str """Identifier for the last eval from the previous pagination request.""" limit: int """Number of evals to retrieve.""" order: Literal["asc", "desc"] """Sort order for evals by timestamp. Use `asc` for ascending order or `desc` for descending order. """ order_by: Literal["created_at", "updated_at"] """Evals can be ordered by creation time or last updated time. Use `created_at` for creation time or `updated_at` for last updated time. """ ================================================ FILE: src/openai/types/eval_list_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo from .._utils import PropertyInfo from .._models import BaseModel from .shared.metadata import Metadata from .graders.python_grader import PythonGrader from .graders.label_model_grader import LabelModelGrader from .graders.score_model_grader import ScoreModelGrader from .graders.string_check_grader import StringCheckGrader from .eval_custom_data_source_config import EvalCustomDataSourceConfig from .graders.text_similarity_grader import TextSimilarityGrader from .eval_stored_completions_data_source_config import EvalStoredCompletionsDataSourceConfig __all__ = [ "EvalListResponse", "DataSourceConfig", "DataSourceConfigLogs", "TestingCriterion", "TestingCriterionEvalGraderTextSimilarity", "TestingCriterionEvalGraderPython", "TestingCriterionEvalGraderScoreModel", ] class DataSourceConfigLogs(BaseModel): """ A LogsDataSourceConfig which specifies the metadata property of your logs query. This is usually metadata like `usecase=chatbot` or `prompt-version=v2`, etc. The schema returned by this data source config is used to defined what variables are available in your evals. `item` and `sample` are both defined when using this data source config. """ schema_: Dict[str, object] = FieldInfo(alias="schema") """ The json schema for the run data source items. Learn how to build JSON schemas [here](https://json-schema.org/). """ type: Literal["logs"] """The type of data source. Always `logs`.""" metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ DataSourceConfig: TypeAlias = Annotated[ Union[EvalCustomDataSourceConfig, DataSourceConfigLogs, EvalStoredCompletionsDataSourceConfig], PropertyInfo(discriminator="type"), ] class TestingCriterionEvalGraderTextSimilarity(TextSimilarityGrader): __test__ = False """A TextSimilarityGrader object which grades text based on similarity metrics.""" pass_threshold: float """The threshold for the score.""" class TestingCriterionEvalGraderPython(PythonGrader): __test__ = False """A PythonGrader object that runs a python script on the input.""" pass_threshold: Optional[float] = None """The threshold for the score.""" class TestingCriterionEvalGraderScoreModel(ScoreModelGrader): __test__ = False """A ScoreModelGrader object that uses a model to assign a score to the input.""" pass_threshold: Optional[float] = None """The threshold for the score.""" TestingCriterion: TypeAlias = Union[ LabelModelGrader, StringCheckGrader, TestingCriterionEvalGraderTextSimilarity, TestingCriterionEvalGraderPython, TestingCriterionEvalGraderScoreModel, ] class EvalListResponse(BaseModel): """ An Eval object with a data source config and testing criteria. An Eval represents a task to be done for your LLM integration. Like: - Improve the quality of my chatbot - See how well my chatbot handles customer support - Check if o4-mini is better at my usecase than gpt-4o """ id: str """Unique identifier for the evaluation.""" created_at: int """The Unix timestamp (in seconds) for when the eval was created.""" data_source_config: DataSourceConfig """Configuration of data sources used in runs of the evaluation.""" metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ name: str """The name of the evaluation.""" object: Literal["eval"] """The object type.""" testing_criteria: List[TestingCriterion] """A list of testing criteria.""" ================================================ FILE: src/openai/types/eval_retrieve_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo from .._utils import PropertyInfo from .._models import BaseModel from .shared.metadata import Metadata from .graders.python_grader import PythonGrader from .graders.label_model_grader import LabelModelGrader from .graders.score_model_grader import ScoreModelGrader from .graders.string_check_grader import StringCheckGrader from .eval_custom_data_source_config import EvalCustomDataSourceConfig from .graders.text_similarity_grader import TextSimilarityGrader from .eval_stored_completions_data_source_config import EvalStoredCompletionsDataSourceConfig __all__ = [ "EvalRetrieveResponse", "DataSourceConfig", "DataSourceConfigLogs", "TestingCriterion", "TestingCriterionEvalGraderTextSimilarity", "TestingCriterionEvalGraderPython", "TestingCriterionEvalGraderScoreModel", ] class DataSourceConfigLogs(BaseModel): """ A LogsDataSourceConfig which specifies the metadata property of your logs query. This is usually metadata like `usecase=chatbot` or `prompt-version=v2`, etc. The schema returned by this data source config is used to defined what variables are available in your evals. `item` and `sample` are both defined when using this data source config. """ schema_: Dict[str, object] = FieldInfo(alias="schema") """ The json schema for the run data source items. Learn how to build JSON schemas [here](https://json-schema.org/). """ type: Literal["logs"] """The type of data source. Always `logs`.""" metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ DataSourceConfig: TypeAlias = Annotated[ Union[EvalCustomDataSourceConfig, DataSourceConfigLogs, EvalStoredCompletionsDataSourceConfig], PropertyInfo(discriminator="type"), ] class TestingCriterionEvalGraderTextSimilarity(TextSimilarityGrader): __test__ = False """A TextSimilarityGrader object which grades text based on similarity metrics.""" pass_threshold: float """The threshold for the score.""" class TestingCriterionEvalGraderPython(PythonGrader): __test__ = False """A PythonGrader object that runs a python script on the input.""" pass_threshold: Optional[float] = None """The threshold for the score.""" class TestingCriterionEvalGraderScoreModel(ScoreModelGrader): __test__ = False """A ScoreModelGrader object that uses a model to assign a score to the input.""" pass_threshold: Optional[float] = None """The threshold for the score.""" TestingCriterion: TypeAlias = Union[ LabelModelGrader, StringCheckGrader, TestingCriterionEvalGraderTextSimilarity, TestingCriterionEvalGraderPython, TestingCriterionEvalGraderScoreModel, ] class EvalRetrieveResponse(BaseModel): """ An Eval object with a data source config and testing criteria. An Eval represents a task to be done for your LLM integration. Like: - Improve the quality of my chatbot - See how well my chatbot handles customer support - Check if o4-mini is better at my usecase than gpt-4o """ id: str """Unique identifier for the evaluation.""" created_at: int """The Unix timestamp (in seconds) for when the eval was created.""" data_source_config: DataSourceConfig """Configuration of data sources used in runs of the evaluation.""" metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ name: str """The name of the evaluation.""" object: Literal["eval"] """The object type.""" testing_criteria: List[TestingCriterion] """A list of testing criteria.""" ================================================ FILE: src/openai/types/eval_stored_completions_data_source_config.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, Optional from typing_extensions import Literal from pydantic import Field as FieldInfo from .._models import BaseModel from .shared.metadata import Metadata __all__ = ["EvalStoredCompletionsDataSourceConfig"] class EvalStoredCompletionsDataSourceConfig(BaseModel): """Deprecated in favor of LogsDataSourceConfig.""" schema_: Dict[str, object] = FieldInfo(alias="schema") """ The json schema for the run data source items. Learn how to build JSON schemas [here](https://json-schema.org/). """ type: Literal["stored_completions"] """The type of data source. Always `stored_completions`.""" metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ ================================================ FILE: src/openai/types/eval_update_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import TypedDict from .shared_params.metadata import Metadata __all__ = ["EvalUpdateParams"] class EvalUpdateParams(TypedDict, total=False): metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ name: str """Rename the evaluation.""" ================================================ FILE: src/openai/types/eval_update_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo from .._utils import PropertyInfo from .._models import BaseModel from .shared.metadata import Metadata from .graders.python_grader import PythonGrader from .graders.label_model_grader import LabelModelGrader from .graders.score_model_grader import ScoreModelGrader from .graders.string_check_grader import StringCheckGrader from .eval_custom_data_source_config import EvalCustomDataSourceConfig from .graders.text_similarity_grader import TextSimilarityGrader from .eval_stored_completions_data_source_config import EvalStoredCompletionsDataSourceConfig __all__ = [ "EvalUpdateResponse", "DataSourceConfig", "DataSourceConfigLogs", "TestingCriterion", "TestingCriterionEvalGraderTextSimilarity", "TestingCriterionEvalGraderPython", "TestingCriterionEvalGraderScoreModel", ] class DataSourceConfigLogs(BaseModel): """ A LogsDataSourceConfig which specifies the metadata property of your logs query. This is usually metadata like `usecase=chatbot` or `prompt-version=v2`, etc. The schema returned by this data source config is used to defined what variables are available in your evals. `item` and `sample` are both defined when using this data source config. """ schema_: Dict[str, object] = FieldInfo(alias="schema") """ The json schema for the run data source items. Learn how to build JSON schemas [here](https://json-schema.org/). """ type: Literal["logs"] """The type of data source. Always `logs`.""" metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ DataSourceConfig: TypeAlias = Annotated[ Union[EvalCustomDataSourceConfig, DataSourceConfigLogs, EvalStoredCompletionsDataSourceConfig], PropertyInfo(discriminator="type"), ] class TestingCriterionEvalGraderTextSimilarity(TextSimilarityGrader): __test__ = False """A TextSimilarityGrader object which grades text based on similarity metrics.""" pass_threshold: float """The threshold for the score.""" class TestingCriterionEvalGraderPython(PythonGrader): __test__ = False """A PythonGrader object that runs a python script on the input.""" pass_threshold: Optional[float] = None """The threshold for the score.""" class TestingCriterionEvalGraderScoreModel(ScoreModelGrader): __test__ = False """A ScoreModelGrader object that uses a model to assign a score to the input.""" pass_threshold: Optional[float] = None """The threshold for the score.""" TestingCriterion: TypeAlias = Union[ LabelModelGrader, StringCheckGrader, TestingCriterionEvalGraderTextSimilarity, TestingCriterionEvalGraderPython, TestingCriterionEvalGraderScoreModel, ] class EvalUpdateResponse(BaseModel): """ An Eval object with a data source config and testing criteria. An Eval represents a task to be done for your LLM integration. Like: - Improve the quality of my chatbot - See how well my chatbot handles customer support - Check if o4-mini is better at my usecase than gpt-4o """ id: str """Unique identifier for the evaluation.""" created_at: int """The Unix timestamp (in seconds) for when the eval was created.""" data_source_config: DataSourceConfig """Configuration of data sources used in runs of the evaluation.""" metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ name: str """The name of the evaluation.""" object: Literal["eval"] """The object type.""" testing_criteria: List[TestingCriterion] """A list of testing criteria.""" ================================================ FILE: src/openai/types/evals/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .eval_api_error import EvalAPIError as EvalAPIError from .run_list_params import RunListParams as RunListParams from .run_create_params import RunCreateParams as RunCreateParams from .run_list_response import RunListResponse as RunListResponse from .run_cancel_response import RunCancelResponse as RunCancelResponse from .run_create_response import RunCreateResponse as RunCreateResponse from .run_delete_response import RunDeleteResponse as RunDeleteResponse from .run_retrieve_response import RunRetrieveResponse as RunRetrieveResponse from .create_eval_jsonl_run_data_source import CreateEvalJSONLRunDataSource as CreateEvalJSONLRunDataSource from .create_eval_completions_run_data_source import ( CreateEvalCompletionsRunDataSource as CreateEvalCompletionsRunDataSource, ) from .create_eval_jsonl_run_data_source_param import ( CreateEvalJSONLRunDataSourceParam as CreateEvalJSONLRunDataSourceParam, ) from .create_eval_completions_run_data_source_param import ( CreateEvalCompletionsRunDataSourceParam as CreateEvalCompletionsRunDataSourceParam, ) ================================================ FILE: src/openai/types/evals/create_eval_completions_run_data_source.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from ..shared.metadata import Metadata from ..graders.grader_inputs import GraderInputs from ..shared.reasoning_effort import ReasoningEffort from ..shared.response_format_text import ResponseFormatText from ..responses.easy_input_message import EasyInputMessage from ..responses.response_input_text import ResponseInputText from ..responses.response_input_audio import ResponseInputAudio from ..chat.chat_completion_function_tool import ChatCompletionFunctionTool from ..shared.response_format_json_object import ResponseFormatJSONObject from ..shared.response_format_json_schema import ResponseFormatJSONSchema __all__ = [ "CreateEvalCompletionsRunDataSource", "Source", "SourceFileContent", "SourceFileContentContent", "SourceFileID", "SourceStoredCompletions", "InputMessages", "InputMessagesTemplate", "InputMessagesTemplateTemplate", "InputMessagesTemplateTemplateEvalItem", "InputMessagesTemplateTemplateEvalItemContent", "InputMessagesTemplateTemplateEvalItemContentOutputText", "InputMessagesTemplateTemplateEvalItemContentInputImage", "InputMessagesItemReference", "SamplingParams", "SamplingParamsResponseFormat", ] class SourceFileContentContent(BaseModel): item: Dict[str, object] sample: Optional[Dict[str, object]] = None class SourceFileContent(BaseModel): content: List[SourceFileContentContent] """The content of the jsonl file.""" type: Literal["file_content"] """The type of jsonl source. Always `file_content`.""" class SourceFileID(BaseModel): id: str """The identifier of the file.""" type: Literal["file_id"] """The type of jsonl source. Always `file_id`.""" class SourceStoredCompletions(BaseModel): """A StoredCompletionsRunDataSource configuration describing a set of filters""" type: Literal["stored_completions"] """The type of source. Always `stored_completions`.""" created_after: Optional[int] = None """An optional Unix timestamp to filter items created after this time.""" created_before: Optional[int] = None """An optional Unix timestamp to filter items created before this time.""" limit: Optional[int] = None """An optional maximum number of items to return.""" metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ model: Optional[str] = None """An optional model to filter by (e.g., 'gpt-4o').""" Source: TypeAlias = Annotated[ Union[SourceFileContent, SourceFileID, SourceStoredCompletions], PropertyInfo(discriminator="type") ] class InputMessagesTemplateTemplateEvalItemContentOutputText(BaseModel): """A text output from the model.""" text: str """The text output from the model.""" type: Literal["output_text"] """The type of the output text. Always `output_text`.""" class InputMessagesTemplateTemplateEvalItemContentInputImage(BaseModel): """An image input block used within EvalItem content arrays.""" image_url: str """The URL of the image input.""" type: Literal["input_image"] """The type of the image input. Always `input_image`.""" detail: Optional[str] = None """The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. Defaults to `auto`. """ InputMessagesTemplateTemplateEvalItemContent: TypeAlias = Union[ str, ResponseInputText, InputMessagesTemplateTemplateEvalItemContentOutputText, InputMessagesTemplateTemplateEvalItemContentInputImage, ResponseInputAudio, GraderInputs, ] class InputMessagesTemplateTemplateEvalItem(BaseModel): """ A message input to the model with a role indicating instruction following hierarchy. Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role. Messages with the `assistant` role are presumed to have been generated by the model in previous interactions. """ content: InputMessagesTemplateTemplateEvalItemContent """Inputs to the model - can contain template strings. Supports text, output text, input images, and input audio, either as a single item or an array of items. """ role: Literal["user", "assistant", "system", "developer"] """The role of the message input. One of `user`, `assistant`, `system`, or `developer`. """ type: Optional[Literal["message"]] = None """The type of the message input. Always `message`.""" InputMessagesTemplateTemplate: TypeAlias = Union[EasyInputMessage, InputMessagesTemplateTemplateEvalItem] class InputMessagesTemplate(BaseModel): template: List[InputMessagesTemplateTemplate] """A list of chat messages forming the prompt or context. May include variable references to the `item` namespace, ie {{item.name}}. """ type: Literal["template"] """The type of input messages. Always `template`.""" class InputMessagesItemReference(BaseModel): item_reference: str """A reference to a variable in the `item` namespace. Ie, "item.input_trajectory" """ type: Literal["item_reference"] """The type of input messages. Always `item_reference`.""" InputMessages: TypeAlias = Annotated[ Union[InputMessagesTemplate, InputMessagesItemReference], PropertyInfo(discriminator="type") ] SamplingParamsResponseFormat: TypeAlias = Union[ResponseFormatText, ResponseFormatJSONSchema, ResponseFormatJSONObject] class SamplingParams(BaseModel): max_completion_tokens: Optional[int] = None """The maximum number of tokens in the generated output.""" reasoning_effort: Optional[ReasoningEffort] = None """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ response_format: Optional[SamplingParamsResponseFormat] = None """An object specifying the format that the model must output. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables the older JSON mode, which ensures the message the model generates is valid JSON. Using `json_schema` is preferred for models that support it. """ seed: Optional[int] = None """A seed value to initialize the randomness, during sampling.""" temperature: Optional[float] = None """A higher temperature increases randomness in the outputs.""" tools: Optional[List[ChatCompletionFunctionTool]] = None """A list of tools the model may call. Currently, only functions are supported as a tool. Use this to provide a list of functions the model may generate JSON inputs for. A max of 128 functions are supported. """ top_p: Optional[float] = None """An alternative to temperature for nucleus sampling; 1.0 includes all tokens.""" class CreateEvalCompletionsRunDataSource(BaseModel): """A CompletionsRunDataSource object describing a model sampling configuration.""" source: Source """Determines what populates the `item` namespace in this run's data source.""" type: Literal["completions"] """The type of run data source. Always `completions`.""" input_messages: Optional[InputMessages] = None """Used when sampling from a model. Dictates the structure of the messages passed into the model. Can either be a reference to a prebuilt trajectory (ie, `item.input_trajectory`), or a template with variable references to the `item` namespace. """ model: Optional[str] = None """The name of the model to use for generating completions (e.g. "o3-mini").""" sampling_params: Optional[SamplingParams] = None ================================================ FILE: src/openai/types/evals/create_eval_completions_run_data_source_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..shared_params.metadata import Metadata from ..shared.reasoning_effort import ReasoningEffort from ..graders.grader_inputs_param import GraderInputsParam from ..responses.easy_input_message_param import EasyInputMessageParam from ..shared_params.response_format_text import ResponseFormatText from ..responses.response_input_text_param import ResponseInputTextParam from ..responses.response_input_audio_param import ResponseInputAudioParam from ..chat.chat_completion_function_tool_param import ChatCompletionFunctionToolParam from ..shared_params.response_format_json_object import ResponseFormatJSONObject from ..shared_params.response_format_json_schema import ResponseFormatJSONSchema __all__ = [ "CreateEvalCompletionsRunDataSourceParam", "Source", "SourceFileContent", "SourceFileContentContent", "SourceFileID", "SourceStoredCompletions", "InputMessages", "InputMessagesTemplate", "InputMessagesTemplateTemplate", "InputMessagesTemplateTemplateEvalItem", "InputMessagesTemplateTemplateEvalItemContent", "InputMessagesTemplateTemplateEvalItemContentOutputText", "InputMessagesTemplateTemplateEvalItemContentInputImage", "InputMessagesItemReference", "SamplingParams", "SamplingParamsResponseFormat", ] class SourceFileContentContent(TypedDict, total=False): item: Required[Dict[str, object]] sample: Dict[str, object] class SourceFileContent(TypedDict, total=False): content: Required[Iterable[SourceFileContentContent]] """The content of the jsonl file.""" type: Required[Literal["file_content"]] """The type of jsonl source. Always `file_content`.""" class SourceFileID(TypedDict, total=False): id: Required[str] """The identifier of the file.""" type: Required[Literal["file_id"]] """The type of jsonl source. Always `file_id`.""" class SourceStoredCompletions(TypedDict, total=False): """A StoredCompletionsRunDataSource configuration describing a set of filters""" type: Required[Literal["stored_completions"]] """The type of source. Always `stored_completions`.""" created_after: Optional[int] """An optional Unix timestamp to filter items created after this time.""" created_before: Optional[int] """An optional Unix timestamp to filter items created before this time.""" limit: Optional[int] """An optional maximum number of items to return.""" metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ model: Optional[str] """An optional model to filter by (e.g., 'gpt-4o').""" Source: TypeAlias = Union[SourceFileContent, SourceFileID, SourceStoredCompletions] class InputMessagesTemplateTemplateEvalItemContentOutputText(TypedDict, total=False): """A text output from the model.""" text: Required[str] """The text output from the model.""" type: Required[Literal["output_text"]] """The type of the output text. Always `output_text`.""" class InputMessagesTemplateTemplateEvalItemContentInputImage(TypedDict, total=False): """An image input block used within EvalItem content arrays.""" image_url: Required[str] """The URL of the image input.""" type: Required[Literal["input_image"]] """The type of the image input. Always `input_image`.""" detail: str """The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. Defaults to `auto`. """ InputMessagesTemplateTemplateEvalItemContent: TypeAlias = Union[ str, ResponseInputTextParam, InputMessagesTemplateTemplateEvalItemContentOutputText, InputMessagesTemplateTemplateEvalItemContentInputImage, ResponseInputAudioParam, GraderInputsParam, ] class InputMessagesTemplateTemplateEvalItem(TypedDict, total=False): """ A message input to the model with a role indicating instruction following hierarchy. Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role. Messages with the `assistant` role are presumed to have been generated by the model in previous interactions. """ content: Required[InputMessagesTemplateTemplateEvalItemContent] """Inputs to the model - can contain template strings. Supports text, output text, input images, and input audio, either as a single item or an array of items. """ role: Required[Literal["user", "assistant", "system", "developer"]] """The role of the message input. One of `user`, `assistant`, `system`, or `developer`. """ type: Literal["message"] """The type of the message input. Always `message`.""" InputMessagesTemplateTemplate: TypeAlias = Union[EasyInputMessageParam, InputMessagesTemplateTemplateEvalItem] class InputMessagesTemplate(TypedDict, total=False): template: Required[Iterable[InputMessagesTemplateTemplate]] """A list of chat messages forming the prompt or context. May include variable references to the `item` namespace, ie {{item.name}}. """ type: Required[Literal["template"]] """The type of input messages. Always `template`.""" class InputMessagesItemReference(TypedDict, total=False): item_reference: Required[str] """A reference to a variable in the `item` namespace. Ie, "item.input_trajectory" """ type: Required[Literal["item_reference"]] """The type of input messages. Always `item_reference`.""" InputMessages: TypeAlias = Union[InputMessagesTemplate, InputMessagesItemReference] SamplingParamsResponseFormat: TypeAlias = Union[ResponseFormatText, ResponseFormatJSONSchema, ResponseFormatJSONObject] class SamplingParams(TypedDict, total=False): max_completion_tokens: int """The maximum number of tokens in the generated output.""" reasoning_effort: Optional[ReasoningEffort] """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ response_format: SamplingParamsResponseFormat """An object specifying the format that the model must output. Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). Setting to `{ "type": "json_object" }` enables the older JSON mode, which ensures the message the model generates is valid JSON. Using `json_schema` is preferred for models that support it. """ seed: int """A seed value to initialize the randomness, during sampling.""" temperature: float """A higher temperature increases randomness in the outputs.""" tools: Iterable[ChatCompletionFunctionToolParam] """A list of tools the model may call. Currently, only functions are supported as a tool. Use this to provide a list of functions the model may generate JSON inputs for. A max of 128 functions are supported. """ top_p: float """An alternative to temperature for nucleus sampling; 1.0 includes all tokens.""" class CreateEvalCompletionsRunDataSourceParam(TypedDict, total=False): """A CompletionsRunDataSource object describing a model sampling configuration.""" source: Required[Source] """Determines what populates the `item` namespace in this run's data source.""" type: Required[Literal["completions"]] """The type of run data source. Always `completions`.""" input_messages: InputMessages """Used when sampling from a model. Dictates the structure of the messages passed into the model. Can either be a reference to a prebuilt trajectory (ie, `item.input_trajectory`), or a template with variable references to the `item` namespace. """ model: str """The name of the model to use for generating completions (e.g. "o3-mini").""" sampling_params: SamplingParams ================================================ FILE: src/openai/types/evals/create_eval_jsonl_run_data_source.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = ["CreateEvalJSONLRunDataSource", "Source", "SourceFileContent", "SourceFileContentContent", "SourceFileID"] class SourceFileContentContent(BaseModel): item: Dict[str, object] sample: Optional[Dict[str, object]] = None class SourceFileContent(BaseModel): content: List[SourceFileContentContent] """The content of the jsonl file.""" type: Literal["file_content"] """The type of jsonl source. Always `file_content`.""" class SourceFileID(BaseModel): id: str """The identifier of the file.""" type: Literal["file_id"] """The type of jsonl source. Always `file_id`.""" Source: TypeAlias = Annotated[Union[SourceFileContent, SourceFileID], PropertyInfo(discriminator="type")] class CreateEvalJSONLRunDataSource(BaseModel): """ A JsonlRunDataSource object with that specifies a JSONL file that matches the eval """ source: Source """Determines what populates the `item` namespace in the data source.""" type: Literal["jsonl"] """The type of data source. Always `jsonl`.""" ================================================ FILE: src/openai/types/evals/create_eval_jsonl_run_data_source_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Union, Iterable from typing_extensions import Literal, Required, TypeAlias, TypedDict __all__ = [ "CreateEvalJSONLRunDataSourceParam", "Source", "SourceFileContent", "SourceFileContentContent", "SourceFileID", ] class SourceFileContentContent(TypedDict, total=False): item: Required[Dict[str, object]] sample: Dict[str, object] class SourceFileContent(TypedDict, total=False): content: Required[Iterable[SourceFileContentContent]] """The content of the jsonl file.""" type: Required[Literal["file_content"]] """The type of jsonl source. Always `file_content`.""" class SourceFileID(TypedDict, total=False): id: Required[str] """The identifier of the file.""" type: Required[Literal["file_id"]] """The type of jsonl source. Always `file_id`.""" Source: TypeAlias = Union[SourceFileContent, SourceFileID] class CreateEvalJSONLRunDataSourceParam(TypedDict, total=False): """ A JsonlRunDataSource object with that specifies a JSONL file that matches the eval """ source: Required[Source] """Determines what populates the `item` namespace in the data source.""" type: Required[Literal["jsonl"]] """The type of data source. Always `jsonl`.""" ================================================ FILE: src/openai/types/evals/eval_api_error.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from ..._models import BaseModel __all__ = ["EvalAPIError"] class EvalAPIError(BaseModel): """An object representing an error response from the Eval API.""" code: str """The error code.""" message: str """The error message.""" ================================================ FILE: src/openai/types/evals/run_cancel_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo from ..._utils import PropertyInfo from ..._models import BaseModel from .eval_api_error import EvalAPIError from ..responses.tool import Tool from ..shared.metadata import Metadata from ..graders.grader_inputs import GraderInputs from ..shared.reasoning_effort import ReasoningEffort from ..responses.response_input_text import ResponseInputText from ..responses.response_input_audio import ResponseInputAudio from .create_eval_jsonl_run_data_source import CreateEvalJSONLRunDataSource from ..responses.response_format_text_config import ResponseFormatTextConfig from .create_eval_completions_run_data_source import CreateEvalCompletionsRunDataSource __all__ = [ "RunCancelResponse", "DataSource", "DataSourceResponses", "DataSourceResponsesSource", "DataSourceResponsesSourceFileContent", "DataSourceResponsesSourceFileContentContent", "DataSourceResponsesSourceFileID", "DataSourceResponsesSourceResponses", "DataSourceResponsesInputMessages", "DataSourceResponsesInputMessagesTemplate", "DataSourceResponsesInputMessagesTemplateTemplate", "DataSourceResponsesInputMessagesTemplateTemplateChatMessage", "DataSourceResponsesInputMessagesTemplateTemplateEvalItem", "DataSourceResponsesInputMessagesTemplateTemplateEvalItemContent", "DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentOutputText", "DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentInputImage", "DataSourceResponsesInputMessagesItemReference", "DataSourceResponsesSamplingParams", "DataSourceResponsesSamplingParamsText", "PerModelUsage", "PerTestingCriteriaResult", "ResultCounts", ] class DataSourceResponsesSourceFileContentContent(BaseModel): item: Dict[str, object] sample: Optional[Dict[str, object]] = None class DataSourceResponsesSourceFileContent(BaseModel): content: List[DataSourceResponsesSourceFileContentContent] """The content of the jsonl file.""" type: Literal["file_content"] """The type of jsonl source. Always `file_content`.""" class DataSourceResponsesSourceFileID(BaseModel): id: str """The identifier of the file.""" type: Literal["file_id"] """The type of jsonl source. Always `file_id`.""" class DataSourceResponsesSourceResponses(BaseModel): """A EvalResponsesSource object describing a run data source configuration.""" type: Literal["responses"] """The type of run data source. Always `responses`.""" created_after: Optional[int] = None """Only include items created after this timestamp (inclusive). This is a query parameter used to select responses. """ created_before: Optional[int] = None """Only include items created before this timestamp (inclusive). This is a query parameter used to select responses. """ instructions_search: Optional[str] = None """Optional string to search the 'instructions' field. This is a query parameter used to select responses. """ metadata: Optional[object] = None """Metadata filter for the responses. This is a query parameter used to select responses. """ model: Optional[str] = None """The name of the model to find responses for. This is a query parameter used to select responses. """ reasoning_effort: Optional[ReasoningEffort] = None """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ temperature: Optional[float] = None """Sampling temperature. This is a query parameter used to select responses.""" tools: Optional[List[str]] = None """List of tool names. This is a query parameter used to select responses.""" top_p: Optional[float] = None """Nucleus sampling parameter. This is a query parameter used to select responses.""" users: Optional[List[str]] = None """List of user identifiers. This is a query parameter used to select responses.""" DataSourceResponsesSource: TypeAlias = Annotated[ Union[DataSourceResponsesSourceFileContent, DataSourceResponsesSourceFileID, DataSourceResponsesSourceResponses], PropertyInfo(discriminator="type"), ] class DataSourceResponsesInputMessagesTemplateTemplateChatMessage(BaseModel): content: str """The content of the message.""" role: str """The role of the message (e.g. "system", "assistant", "user").""" class DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentOutputText(BaseModel): """A text output from the model.""" text: str """The text output from the model.""" type: Literal["output_text"] """The type of the output text. Always `output_text`.""" class DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentInputImage(BaseModel): """An image input block used within EvalItem content arrays.""" image_url: str """The URL of the image input.""" type: Literal["input_image"] """The type of the image input. Always `input_image`.""" detail: Optional[str] = None """The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. Defaults to `auto`. """ DataSourceResponsesInputMessagesTemplateTemplateEvalItemContent: TypeAlias = Union[ str, ResponseInputText, DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentOutputText, DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentInputImage, ResponseInputAudio, GraderInputs, ] class DataSourceResponsesInputMessagesTemplateTemplateEvalItem(BaseModel): """ A message input to the model with a role indicating instruction following hierarchy. Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role. Messages with the `assistant` role are presumed to have been generated by the model in previous interactions. """ content: DataSourceResponsesInputMessagesTemplateTemplateEvalItemContent """Inputs to the model - can contain template strings. Supports text, output text, input images, and input audio, either as a single item or an array of items. """ role: Literal["user", "assistant", "system", "developer"] """The role of the message input. One of `user`, `assistant`, `system`, or `developer`. """ type: Optional[Literal["message"]] = None """The type of the message input. Always `message`.""" DataSourceResponsesInputMessagesTemplateTemplate: TypeAlias = Union[ DataSourceResponsesInputMessagesTemplateTemplateChatMessage, DataSourceResponsesInputMessagesTemplateTemplateEvalItem, ] class DataSourceResponsesInputMessagesTemplate(BaseModel): template: List[DataSourceResponsesInputMessagesTemplateTemplate] """A list of chat messages forming the prompt or context. May include variable references to the `item` namespace, ie {{item.name}}. """ type: Literal["template"] """The type of input messages. Always `template`.""" class DataSourceResponsesInputMessagesItemReference(BaseModel): item_reference: str """A reference to a variable in the `item` namespace. Ie, "item.name" """ type: Literal["item_reference"] """The type of input messages. Always `item_reference`.""" DataSourceResponsesInputMessages: TypeAlias = Annotated[ Union[DataSourceResponsesInputMessagesTemplate, DataSourceResponsesInputMessagesItemReference], PropertyInfo(discriminator="type"), ] class DataSourceResponsesSamplingParamsText(BaseModel): """Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) """ format: Optional[ResponseFormatTextConfig] = None """An object specifying the format that the model must output. Configuring `{ "type": "json_schema" }` enables Structured Outputs, which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). The default format is `{ "type": "text" }` with no additional options. **Not recommended for gpt-4o and newer models:** Setting to `{ "type": "json_object" }` enables the older JSON mode, which ensures the message the model generates is valid JSON. Using `json_schema` is preferred for models that support it. """ class DataSourceResponsesSamplingParams(BaseModel): max_completion_tokens: Optional[int] = None """The maximum number of tokens in the generated output.""" reasoning_effort: Optional[ReasoningEffort] = None """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ seed: Optional[int] = None """A seed value to initialize the randomness, during sampling.""" temperature: Optional[float] = None """A higher temperature increases randomness in the outputs.""" text: Optional[DataSourceResponsesSamplingParamsText] = None """Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) """ tools: Optional[List[Tool]] = None """An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. The two categories of tools you can provide the model are: - **Built-in tools**: Tools that are provided by OpenAI that extend the model's capabilities, like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). - **Function calls (custom tools)**: Functions that are defined by you, enabling the model to call your own code. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). """ top_p: Optional[float] = None """An alternative to temperature for nucleus sampling; 1.0 includes all tokens.""" class DataSourceResponses(BaseModel): """A ResponsesRunDataSource object describing a model sampling configuration.""" source: DataSourceResponsesSource """Determines what populates the `item` namespace in this run's data source.""" type: Literal["responses"] """The type of run data source. Always `responses`.""" input_messages: Optional[DataSourceResponsesInputMessages] = None """Used when sampling from a model. Dictates the structure of the messages passed into the model. Can either be a reference to a prebuilt trajectory (ie, `item.input_trajectory`), or a template with variable references to the `item` namespace. """ model: Optional[str] = None """The name of the model to use for generating completions (e.g. "o3-mini").""" sampling_params: Optional[DataSourceResponsesSamplingParams] = None DataSource: TypeAlias = Annotated[ Union[CreateEvalJSONLRunDataSource, CreateEvalCompletionsRunDataSource, DataSourceResponses], PropertyInfo(discriminator="type"), ] class PerModelUsage(BaseModel): cached_tokens: int """The number of tokens retrieved from cache.""" completion_tokens: int """The number of completion tokens generated.""" invocation_count: int """The number of invocations.""" run_model_name: str = FieldInfo(alias="model_name") """The name of the model.""" prompt_tokens: int """The number of prompt tokens used.""" total_tokens: int """The total number of tokens used.""" class PerTestingCriteriaResult(BaseModel): failed: int """Number of tests failed for this criteria.""" passed: int """Number of tests passed for this criteria.""" testing_criteria: str """A description of the testing criteria.""" class ResultCounts(BaseModel): """Counters summarizing the outcomes of the evaluation run.""" errored: int """Number of output items that resulted in an error.""" failed: int """Number of output items that failed to pass the evaluation.""" passed: int """Number of output items that passed the evaluation.""" total: int """Total number of executed output items.""" class RunCancelResponse(BaseModel): """A schema representing an evaluation run.""" id: str """Unique identifier for the evaluation run.""" created_at: int """Unix timestamp (in seconds) when the evaluation run was created.""" data_source: DataSource """Information about the run's data source.""" error: EvalAPIError """An object representing an error response from the Eval API.""" eval_id: str """The identifier of the associated evaluation.""" metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ model: str """The model that is evaluated, if applicable.""" name: str """The name of the evaluation run.""" object: Literal["eval.run"] """The type of the object. Always "eval.run".""" per_model_usage: List[PerModelUsage] """Usage statistics for each model during the evaluation run.""" per_testing_criteria_results: List[PerTestingCriteriaResult] """Results per testing criteria applied during the evaluation run.""" report_url: str """The URL to the rendered evaluation run report on the UI dashboard.""" result_counts: ResultCounts """Counters summarizing the outcomes of the evaluation run.""" status: str """The status of the evaluation run.""" ================================================ FILE: src/openai/types/evals/run_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import SequenceNotStr from ..responses.tool_param import ToolParam from ..shared_params.metadata import Metadata from ..shared.reasoning_effort import ReasoningEffort from ..graders.grader_inputs_param import GraderInputsParam from ..responses.response_input_text_param import ResponseInputTextParam from ..responses.response_input_audio_param import ResponseInputAudioParam from .create_eval_jsonl_run_data_source_param import CreateEvalJSONLRunDataSourceParam from ..responses.response_format_text_config_param import ResponseFormatTextConfigParam from .create_eval_completions_run_data_source_param import CreateEvalCompletionsRunDataSourceParam __all__ = [ "RunCreateParams", "DataSource", "DataSourceCreateEvalResponsesRunDataSource", "DataSourceCreateEvalResponsesRunDataSourceSource", "DataSourceCreateEvalResponsesRunDataSourceSourceFileContent", "DataSourceCreateEvalResponsesRunDataSourceSourceFileContentContent", "DataSourceCreateEvalResponsesRunDataSourceSourceFileID", "DataSourceCreateEvalResponsesRunDataSourceSourceResponses", "DataSourceCreateEvalResponsesRunDataSourceInputMessages", "DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplate", "DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplateTemplate", "DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplateTemplateChatMessage", "DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplateTemplateEvalItem", "DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplateTemplateEvalItemContent", "DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplateTemplateEvalItemContentOutputText", "DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplateTemplateEvalItemContentInputImage", "DataSourceCreateEvalResponsesRunDataSourceInputMessagesItemReference", "DataSourceCreateEvalResponsesRunDataSourceSamplingParams", "DataSourceCreateEvalResponsesRunDataSourceSamplingParamsText", ] class RunCreateParams(TypedDict, total=False): data_source: Required[DataSource] """Details about the run's data source.""" metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ name: str """The name of the run.""" class DataSourceCreateEvalResponsesRunDataSourceSourceFileContentContent(TypedDict, total=False): item: Required[Dict[str, object]] sample: Dict[str, object] class DataSourceCreateEvalResponsesRunDataSourceSourceFileContent(TypedDict, total=False): content: Required[Iterable[DataSourceCreateEvalResponsesRunDataSourceSourceFileContentContent]] """The content of the jsonl file.""" type: Required[Literal["file_content"]] """The type of jsonl source. Always `file_content`.""" class DataSourceCreateEvalResponsesRunDataSourceSourceFileID(TypedDict, total=False): id: Required[str] """The identifier of the file.""" type: Required[Literal["file_id"]] """The type of jsonl source. Always `file_id`.""" class DataSourceCreateEvalResponsesRunDataSourceSourceResponses(TypedDict, total=False): """A EvalResponsesSource object describing a run data source configuration.""" type: Required[Literal["responses"]] """The type of run data source. Always `responses`.""" created_after: Optional[int] """Only include items created after this timestamp (inclusive). This is a query parameter used to select responses. """ created_before: Optional[int] """Only include items created before this timestamp (inclusive). This is a query parameter used to select responses. """ instructions_search: Optional[str] """Optional string to search the 'instructions' field. This is a query parameter used to select responses. """ metadata: Optional[object] """Metadata filter for the responses. This is a query parameter used to select responses. """ model: Optional[str] """The name of the model to find responses for. This is a query parameter used to select responses. """ reasoning_effort: Optional[ReasoningEffort] """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ temperature: Optional[float] """Sampling temperature. This is a query parameter used to select responses.""" tools: Optional[SequenceNotStr[str]] """List of tool names. This is a query parameter used to select responses.""" top_p: Optional[float] """Nucleus sampling parameter. This is a query parameter used to select responses.""" users: Optional[SequenceNotStr[str]] """List of user identifiers. This is a query parameter used to select responses.""" DataSourceCreateEvalResponsesRunDataSourceSource: TypeAlias = Union[ DataSourceCreateEvalResponsesRunDataSourceSourceFileContent, DataSourceCreateEvalResponsesRunDataSourceSourceFileID, DataSourceCreateEvalResponsesRunDataSourceSourceResponses, ] class DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplateTemplateChatMessage(TypedDict, total=False): content: Required[str] """The content of the message.""" role: Required[str] """The role of the message (e.g. "system", "assistant", "user").""" class DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplateTemplateEvalItemContentOutputText( TypedDict, total=False ): """A text output from the model.""" text: Required[str] """The text output from the model.""" type: Required[Literal["output_text"]] """The type of the output text. Always `output_text`.""" class DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplateTemplateEvalItemContentInputImage( TypedDict, total=False ): """An image input block used within EvalItem content arrays.""" image_url: Required[str] """The URL of the image input.""" type: Required[Literal["input_image"]] """The type of the image input. Always `input_image`.""" detail: str """The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. Defaults to `auto`. """ DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplateTemplateEvalItemContent: TypeAlias = Union[ str, ResponseInputTextParam, DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplateTemplateEvalItemContentOutputText, DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplateTemplateEvalItemContentInputImage, ResponseInputAudioParam, GraderInputsParam, ] class DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplateTemplateEvalItem(TypedDict, total=False): """ A message input to the model with a role indicating instruction following hierarchy. Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role. Messages with the `assistant` role are presumed to have been generated by the model in previous interactions. """ content: Required[DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplateTemplateEvalItemContent] """Inputs to the model - can contain template strings. Supports text, output text, input images, and input audio, either as a single item or an array of items. """ role: Required[Literal["user", "assistant", "system", "developer"]] """The role of the message input. One of `user`, `assistant`, `system`, or `developer`. """ type: Literal["message"] """The type of the message input. Always `message`.""" DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplateTemplate: TypeAlias = Union[ DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplateTemplateChatMessage, DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplateTemplateEvalItem, ] class DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplate(TypedDict, total=False): template: Required[Iterable[DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplateTemplate]] """A list of chat messages forming the prompt or context. May include variable references to the `item` namespace, ie {{item.name}}. """ type: Required[Literal["template"]] """The type of input messages. Always `template`.""" class DataSourceCreateEvalResponsesRunDataSourceInputMessagesItemReference(TypedDict, total=False): item_reference: Required[str] """A reference to a variable in the `item` namespace. Ie, "item.name" """ type: Required[Literal["item_reference"]] """The type of input messages. Always `item_reference`.""" DataSourceCreateEvalResponsesRunDataSourceInputMessages: TypeAlias = Union[ DataSourceCreateEvalResponsesRunDataSourceInputMessagesTemplate, DataSourceCreateEvalResponsesRunDataSourceInputMessagesItemReference, ] class DataSourceCreateEvalResponsesRunDataSourceSamplingParamsText(TypedDict, total=False): """Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) """ format: ResponseFormatTextConfigParam """An object specifying the format that the model must output. Configuring `{ "type": "json_schema" }` enables Structured Outputs, which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). The default format is `{ "type": "text" }` with no additional options. **Not recommended for gpt-4o and newer models:** Setting to `{ "type": "json_object" }` enables the older JSON mode, which ensures the message the model generates is valid JSON. Using `json_schema` is preferred for models that support it. """ class DataSourceCreateEvalResponsesRunDataSourceSamplingParams(TypedDict, total=False): max_completion_tokens: int """The maximum number of tokens in the generated output.""" reasoning_effort: Optional[ReasoningEffort] """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ seed: int """A seed value to initialize the randomness, during sampling.""" temperature: float """A higher temperature increases randomness in the outputs.""" text: DataSourceCreateEvalResponsesRunDataSourceSamplingParamsText """Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) """ tools: Iterable[ToolParam] """An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. The two categories of tools you can provide the model are: - **Built-in tools**: Tools that are provided by OpenAI that extend the model's capabilities, like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). - **Function calls (custom tools)**: Functions that are defined by you, enabling the model to call your own code. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). """ top_p: float """An alternative to temperature for nucleus sampling; 1.0 includes all tokens.""" class DataSourceCreateEvalResponsesRunDataSource(TypedDict, total=False): """A ResponsesRunDataSource object describing a model sampling configuration.""" source: Required[DataSourceCreateEvalResponsesRunDataSourceSource] """Determines what populates the `item` namespace in this run's data source.""" type: Required[Literal["responses"]] """The type of run data source. Always `responses`.""" input_messages: DataSourceCreateEvalResponsesRunDataSourceInputMessages """Used when sampling from a model. Dictates the structure of the messages passed into the model. Can either be a reference to a prebuilt trajectory (ie, `item.input_trajectory`), or a template with variable references to the `item` namespace. """ model: str """The name of the model to use for generating completions (e.g. "o3-mini").""" sampling_params: DataSourceCreateEvalResponsesRunDataSourceSamplingParams DataSource: TypeAlias = Union[ CreateEvalJSONLRunDataSourceParam, CreateEvalCompletionsRunDataSourceParam, DataSourceCreateEvalResponsesRunDataSource, ] ================================================ FILE: src/openai/types/evals/run_create_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo from ..._utils import PropertyInfo from ..._models import BaseModel from .eval_api_error import EvalAPIError from ..responses.tool import Tool from ..shared.metadata import Metadata from ..graders.grader_inputs import GraderInputs from ..shared.reasoning_effort import ReasoningEffort from ..responses.response_input_text import ResponseInputText from ..responses.response_input_audio import ResponseInputAudio from .create_eval_jsonl_run_data_source import CreateEvalJSONLRunDataSource from ..responses.response_format_text_config import ResponseFormatTextConfig from .create_eval_completions_run_data_source import CreateEvalCompletionsRunDataSource __all__ = [ "RunCreateResponse", "DataSource", "DataSourceResponses", "DataSourceResponsesSource", "DataSourceResponsesSourceFileContent", "DataSourceResponsesSourceFileContentContent", "DataSourceResponsesSourceFileID", "DataSourceResponsesSourceResponses", "DataSourceResponsesInputMessages", "DataSourceResponsesInputMessagesTemplate", "DataSourceResponsesInputMessagesTemplateTemplate", "DataSourceResponsesInputMessagesTemplateTemplateChatMessage", "DataSourceResponsesInputMessagesTemplateTemplateEvalItem", "DataSourceResponsesInputMessagesTemplateTemplateEvalItemContent", "DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentOutputText", "DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentInputImage", "DataSourceResponsesInputMessagesItemReference", "DataSourceResponsesSamplingParams", "DataSourceResponsesSamplingParamsText", "PerModelUsage", "PerTestingCriteriaResult", "ResultCounts", ] class DataSourceResponsesSourceFileContentContent(BaseModel): item: Dict[str, object] sample: Optional[Dict[str, object]] = None class DataSourceResponsesSourceFileContent(BaseModel): content: List[DataSourceResponsesSourceFileContentContent] """The content of the jsonl file.""" type: Literal["file_content"] """The type of jsonl source. Always `file_content`.""" class DataSourceResponsesSourceFileID(BaseModel): id: str """The identifier of the file.""" type: Literal["file_id"] """The type of jsonl source. Always `file_id`.""" class DataSourceResponsesSourceResponses(BaseModel): """A EvalResponsesSource object describing a run data source configuration.""" type: Literal["responses"] """The type of run data source. Always `responses`.""" created_after: Optional[int] = None """Only include items created after this timestamp (inclusive). This is a query parameter used to select responses. """ created_before: Optional[int] = None """Only include items created before this timestamp (inclusive). This is a query parameter used to select responses. """ instructions_search: Optional[str] = None """Optional string to search the 'instructions' field. This is a query parameter used to select responses. """ metadata: Optional[object] = None """Metadata filter for the responses. This is a query parameter used to select responses. """ model: Optional[str] = None """The name of the model to find responses for. This is a query parameter used to select responses. """ reasoning_effort: Optional[ReasoningEffort] = None """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ temperature: Optional[float] = None """Sampling temperature. This is a query parameter used to select responses.""" tools: Optional[List[str]] = None """List of tool names. This is a query parameter used to select responses.""" top_p: Optional[float] = None """Nucleus sampling parameter. This is a query parameter used to select responses.""" users: Optional[List[str]] = None """List of user identifiers. This is a query parameter used to select responses.""" DataSourceResponsesSource: TypeAlias = Annotated[ Union[DataSourceResponsesSourceFileContent, DataSourceResponsesSourceFileID, DataSourceResponsesSourceResponses], PropertyInfo(discriminator="type"), ] class DataSourceResponsesInputMessagesTemplateTemplateChatMessage(BaseModel): content: str """The content of the message.""" role: str """The role of the message (e.g. "system", "assistant", "user").""" class DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentOutputText(BaseModel): """A text output from the model.""" text: str """The text output from the model.""" type: Literal["output_text"] """The type of the output text. Always `output_text`.""" class DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentInputImage(BaseModel): """An image input block used within EvalItem content arrays.""" image_url: str """The URL of the image input.""" type: Literal["input_image"] """The type of the image input. Always `input_image`.""" detail: Optional[str] = None """The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. Defaults to `auto`. """ DataSourceResponsesInputMessagesTemplateTemplateEvalItemContent: TypeAlias = Union[ str, ResponseInputText, DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentOutputText, DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentInputImage, ResponseInputAudio, GraderInputs, ] class DataSourceResponsesInputMessagesTemplateTemplateEvalItem(BaseModel): """ A message input to the model with a role indicating instruction following hierarchy. Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role. Messages with the `assistant` role are presumed to have been generated by the model in previous interactions. """ content: DataSourceResponsesInputMessagesTemplateTemplateEvalItemContent """Inputs to the model - can contain template strings. Supports text, output text, input images, and input audio, either as a single item or an array of items. """ role: Literal["user", "assistant", "system", "developer"] """The role of the message input. One of `user`, `assistant`, `system`, or `developer`. """ type: Optional[Literal["message"]] = None """The type of the message input. Always `message`.""" DataSourceResponsesInputMessagesTemplateTemplate: TypeAlias = Union[ DataSourceResponsesInputMessagesTemplateTemplateChatMessage, DataSourceResponsesInputMessagesTemplateTemplateEvalItem, ] class DataSourceResponsesInputMessagesTemplate(BaseModel): template: List[DataSourceResponsesInputMessagesTemplateTemplate] """A list of chat messages forming the prompt or context. May include variable references to the `item` namespace, ie {{item.name}}. """ type: Literal["template"] """The type of input messages. Always `template`.""" class DataSourceResponsesInputMessagesItemReference(BaseModel): item_reference: str """A reference to a variable in the `item` namespace. Ie, "item.name" """ type: Literal["item_reference"] """The type of input messages. Always `item_reference`.""" DataSourceResponsesInputMessages: TypeAlias = Annotated[ Union[DataSourceResponsesInputMessagesTemplate, DataSourceResponsesInputMessagesItemReference], PropertyInfo(discriminator="type"), ] class DataSourceResponsesSamplingParamsText(BaseModel): """Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) """ format: Optional[ResponseFormatTextConfig] = None """An object specifying the format that the model must output. Configuring `{ "type": "json_schema" }` enables Structured Outputs, which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). The default format is `{ "type": "text" }` with no additional options. **Not recommended for gpt-4o and newer models:** Setting to `{ "type": "json_object" }` enables the older JSON mode, which ensures the message the model generates is valid JSON. Using `json_schema` is preferred for models that support it. """ class DataSourceResponsesSamplingParams(BaseModel): max_completion_tokens: Optional[int] = None """The maximum number of tokens in the generated output.""" reasoning_effort: Optional[ReasoningEffort] = None """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ seed: Optional[int] = None """A seed value to initialize the randomness, during sampling.""" temperature: Optional[float] = None """A higher temperature increases randomness in the outputs.""" text: Optional[DataSourceResponsesSamplingParamsText] = None """Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) """ tools: Optional[List[Tool]] = None """An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. The two categories of tools you can provide the model are: - **Built-in tools**: Tools that are provided by OpenAI that extend the model's capabilities, like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). - **Function calls (custom tools)**: Functions that are defined by you, enabling the model to call your own code. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). """ top_p: Optional[float] = None """An alternative to temperature for nucleus sampling; 1.0 includes all tokens.""" class DataSourceResponses(BaseModel): """A ResponsesRunDataSource object describing a model sampling configuration.""" source: DataSourceResponsesSource """Determines what populates the `item` namespace in this run's data source.""" type: Literal["responses"] """The type of run data source. Always `responses`.""" input_messages: Optional[DataSourceResponsesInputMessages] = None """Used when sampling from a model. Dictates the structure of the messages passed into the model. Can either be a reference to a prebuilt trajectory (ie, `item.input_trajectory`), or a template with variable references to the `item` namespace. """ model: Optional[str] = None """The name of the model to use for generating completions (e.g. "o3-mini").""" sampling_params: Optional[DataSourceResponsesSamplingParams] = None DataSource: TypeAlias = Annotated[ Union[CreateEvalJSONLRunDataSource, CreateEvalCompletionsRunDataSource, DataSourceResponses], PropertyInfo(discriminator="type"), ] class PerModelUsage(BaseModel): cached_tokens: int """The number of tokens retrieved from cache.""" completion_tokens: int """The number of completion tokens generated.""" invocation_count: int """The number of invocations.""" run_model_name: str = FieldInfo(alias="model_name") """The name of the model.""" prompt_tokens: int """The number of prompt tokens used.""" total_tokens: int """The total number of tokens used.""" class PerTestingCriteriaResult(BaseModel): failed: int """Number of tests failed for this criteria.""" passed: int """Number of tests passed for this criteria.""" testing_criteria: str """A description of the testing criteria.""" class ResultCounts(BaseModel): """Counters summarizing the outcomes of the evaluation run.""" errored: int """Number of output items that resulted in an error.""" failed: int """Number of output items that failed to pass the evaluation.""" passed: int """Number of output items that passed the evaluation.""" total: int """Total number of executed output items.""" class RunCreateResponse(BaseModel): """A schema representing an evaluation run.""" id: str """Unique identifier for the evaluation run.""" created_at: int """Unix timestamp (in seconds) when the evaluation run was created.""" data_source: DataSource """Information about the run's data source.""" error: EvalAPIError """An object representing an error response from the Eval API.""" eval_id: str """The identifier of the associated evaluation.""" metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ model: str """The model that is evaluated, if applicable.""" name: str """The name of the evaluation run.""" object: Literal["eval.run"] """The type of the object. Always "eval.run".""" per_model_usage: List[PerModelUsage] """Usage statistics for each model during the evaluation run.""" per_testing_criteria_results: List[PerTestingCriteriaResult] """Results per testing criteria applied during the evaluation run.""" report_url: str """The URL to the rendered evaluation run report on the UI dashboard.""" result_counts: ResultCounts """Counters summarizing the outcomes of the evaluation run.""" status: str """The status of the evaluation run.""" ================================================ FILE: src/openai/types/evals/run_delete_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from ..._models import BaseModel __all__ = ["RunDeleteResponse"] class RunDeleteResponse(BaseModel): deleted: Optional[bool] = None object: Optional[str] = None run_id: Optional[str] = None ================================================ FILE: src/openai/types/evals/run_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["RunListParams"] class RunListParams(TypedDict, total=False): after: str """Identifier for the last run from the previous pagination request.""" limit: int """Number of runs to retrieve.""" order: Literal["asc", "desc"] """Sort order for runs by timestamp. Use `asc` for ascending order or `desc` for descending order. Defaults to `asc`. """ status: Literal["queued", "in_progress", "completed", "canceled", "failed"] """Filter runs by status. One of `queued` | `in_progress` | `failed` | `completed` | `canceled`. """ ================================================ FILE: src/openai/types/evals/run_list_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo from ..._utils import PropertyInfo from ..._models import BaseModel from .eval_api_error import EvalAPIError from ..responses.tool import Tool from ..shared.metadata import Metadata from ..graders.grader_inputs import GraderInputs from ..shared.reasoning_effort import ReasoningEffort from ..responses.response_input_text import ResponseInputText from ..responses.response_input_audio import ResponseInputAudio from .create_eval_jsonl_run_data_source import CreateEvalJSONLRunDataSource from ..responses.response_format_text_config import ResponseFormatTextConfig from .create_eval_completions_run_data_source import CreateEvalCompletionsRunDataSource __all__ = [ "RunListResponse", "DataSource", "DataSourceResponses", "DataSourceResponsesSource", "DataSourceResponsesSourceFileContent", "DataSourceResponsesSourceFileContentContent", "DataSourceResponsesSourceFileID", "DataSourceResponsesSourceResponses", "DataSourceResponsesInputMessages", "DataSourceResponsesInputMessagesTemplate", "DataSourceResponsesInputMessagesTemplateTemplate", "DataSourceResponsesInputMessagesTemplateTemplateChatMessage", "DataSourceResponsesInputMessagesTemplateTemplateEvalItem", "DataSourceResponsesInputMessagesTemplateTemplateEvalItemContent", "DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentOutputText", "DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentInputImage", "DataSourceResponsesInputMessagesItemReference", "DataSourceResponsesSamplingParams", "DataSourceResponsesSamplingParamsText", "PerModelUsage", "PerTestingCriteriaResult", "ResultCounts", ] class DataSourceResponsesSourceFileContentContent(BaseModel): item: Dict[str, object] sample: Optional[Dict[str, object]] = None class DataSourceResponsesSourceFileContent(BaseModel): content: List[DataSourceResponsesSourceFileContentContent] """The content of the jsonl file.""" type: Literal["file_content"] """The type of jsonl source. Always `file_content`.""" class DataSourceResponsesSourceFileID(BaseModel): id: str """The identifier of the file.""" type: Literal["file_id"] """The type of jsonl source. Always `file_id`.""" class DataSourceResponsesSourceResponses(BaseModel): """A EvalResponsesSource object describing a run data source configuration.""" type: Literal["responses"] """The type of run data source. Always `responses`.""" created_after: Optional[int] = None """Only include items created after this timestamp (inclusive). This is a query parameter used to select responses. """ created_before: Optional[int] = None """Only include items created before this timestamp (inclusive). This is a query parameter used to select responses. """ instructions_search: Optional[str] = None """Optional string to search the 'instructions' field. This is a query parameter used to select responses. """ metadata: Optional[object] = None """Metadata filter for the responses. This is a query parameter used to select responses. """ model: Optional[str] = None """The name of the model to find responses for. This is a query parameter used to select responses. """ reasoning_effort: Optional[ReasoningEffort] = None """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ temperature: Optional[float] = None """Sampling temperature. This is a query parameter used to select responses.""" tools: Optional[List[str]] = None """List of tool names. This is a query parameter used to select responses.""" top_p: Optional[float] = None """Nucleus sampling parameter. This is a query parameter used to select responses.""" users: Optional[List[str]] = None """List of user identifiers. This is a query parameter used to select responses.""" DataSourceResponsesSource: TypeAlias = Annotated[ Union[DataSourceResponsesSourceFileContent, DataSourceResponsesSourceFileID, DataSourceResponsesSourceResponses], PropertyInfo(discriminator="type"), ] class DataSourceResponsesInputMessagesTemplateTemplateChatMessage(BaseModel): content: str """The content of the message.""" role: str """The role of the message (e.g. "system", "assistant", "user").""" class DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentOutputText(BaseModel): """A text output from the model.""" text: str """The text output from the model.""" type: Literal["output_text"] """The type of the output text. Always `output_text`.""" class DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentInputImage(BaseModel): """An image input block used within EvalItem content arrays.""" image_url: str """The URL of the image input.""" type: Literal["input_image"] """The type of the image input. Always `input_image`.""" detail: Optional[str] = None """The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. Defaults to `auto`. """ DataSourceResponsesInputMessagesTemplateTemplateEvalItemContent: TypeAlias = Union[ str, ResponseInputText, DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentOutputText, DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentInputImage, ResponseInputAudio, GraderInputs, ] class DataSourceResponsesInputMessagesTemplateTemplateEvalItem(BaseModel): """ A message input to the model with a role indicating instruction following hierarchy. Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role. Messages with the `assistant` role are presumed to have been generated by the model in previous interactions. """ content: DataSourceResponsesInputMessagesTemplateTemplateEvalItemContent """Inputs to the model - can contain template strings. Supports text, output text, input images, and input audio, either as a single item or an array of items. """ role: Literal["user", "assistant", "system", "developer"] """The role of the message input. One of `user`, `assistant`, `system`, or `developer`. """ type: Optional[Literal["message"]] = None """The type of the message input. Always `message`.""" DataSourceResponsesInputMessagesTemplateTemplate: TypeAlias = Union[ DataSourceResponsesInputMessagesTemplateTemplateChatMessage, DataSourceResponsesInputMessagesTemplateTemplateEvalItem, ] class DataSourceResponsesInputMessagesTemplate(BaseModel): template: List[DataSourceResponsesInputMessagesTemplateTemplate] """A list of chat messages forming the prompt or context. May include variable references to the `item` namespace, ie {{item.name}}. """ type: Literal["template"] """The type of input messages. Always `template`.""" class DataSourceResponsesInputMessagesItemReference(BaseModel): item_reference: str """A reference to a variable in the `item` namespace. Ie, "item.name" """ type: Literal["item_reference"] """The type of input messages. Always `item_reference`.""" DataSourceResponsesInputMessages: TypeAlias = Annotated[ Union[DataSourceResponsesInputMessagesTemplate, DataSourceResponsesInputMessagesItemReference], PropertyInfo(discriminator="type"), ] class DataSourceResponsesSamplingParamsText(BaseModel): """Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) """ format: Optional[ResponseFormatTextConfig] = None """An object specifying the format that the model must output. Configuring `{ "type": "json_schema" }` enables Structured Outputs, which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). The default format is `{ "type": "text" }` with no additional options. **Not recommended for gpt-4o and newer models:** Setting to `{ "type": "json_object" }` enables the older JSON mode, which ensures the message the model generates is valid JSON. Using `json_schema` is preferred for models that support it. """ class DataSourceResponsesSamplingParams(BaseModel): max_completion_tokens: Optional[int] = None """The maximum number of tokens in the generated output.""" reasoning_effort: Optional[ReasoningEffort] = None """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ seed: Optional[int] = None """A seed value to initialize the randomness, during sampling.""" temperature: Optional[float] = None """A higher temperature increases randomness in the outputs.""" text: Optional[DataSourceResponsesSamplingParamsText] = None """Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) """ tools: Optional[List[Tool]] = None """An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. The two categories of tools you can provide the model are: - **Built-in tools**: Tools that are provided by OpenAI that extend the model's capabilities, like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). - **Function calls (custom tools)**: Functions that are defined by you, enabling the model to call your own code. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). """ top_p: Optional[float] = None """An alternative to temperature for nucleus sampling; 1.0 includes all tokens.""" class DataSourceResponses(BaseModel): """A ResponsesRunDataSource object describing a model sampling configuration.""" source: DataSourceResponsesSource """Determines what populates the `item` namespace in this run's data source.""" type: Literal["responses"] """The type of run data source. Always `responses`.""" input_messages: Optional[DataSourceResponsesInputMessages] = None """Used when sampling from a model. Dictates the structure of the messages passed into the model. Can either be a reference to a prebuilt trajectory (ie, `item.input_trajectory`), or a template with variable references to the `item` namespace. """ model: Optional[str] = None """The name of the model to use for generating completions (e.g. "o3-mini").""" sampling_params: Optional[DataSourceResponsesSamplingParams] = None DataSource: TypeAlias = Annotated[ Union[CreateEvalJSONLRunDataSource, CreateEvalCompletionsRunDataSource, DataSourceResponses], PropertyInfo(discriminator="type"), ] class PerModelUsage(BaseModel): cached_tokens: int """The number of tokens retrieved from cache.""" completion_tokens: int """The number of completion tokens generated.""" invocation_count: int """The number of invocations.""" run_model_name: str = FieldInfo(alias="model_name") """The name of the model.""" prompt_tokens: int """The number of prompt tokens used.""" total_tokens: int """The total number of tokens used.""" class PerTestingCriteriaResult(BaseModel): failed: int """Number of tests failed for this criteria.""" passed: int """Number of tests passed for this criteria.""" testing_criteria: str """A description of the testing criteria.""" class ResultCounts(BaseModel): """Counters summarizing the outcomes of the evaluation run.""" errored: int """Number of output items that resulted in an error.""" failed: int """Number of output items that failed to pass the evaluation.""" passed: int """Number of output items that passed the evaluation.""" total: int """Total number of executed output items.""" class RunListResponse(BaseModel): """A schema representing an evaluation run.""" id: str """Unique identifier for the evaluation run.""" created_at: int """Unix timestamp (in seconds) when the evaluation run was created.""" data_source: DataSource """Information about the run's data source.""" error: EvalAPIError """An object representing an error response from the Eval API.""" eval_id: str """The identifier of the associated evaluation.""" metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ model: str """The model that is evaluated, if applicable.""" name: str """The name of the evaluation run.""" object: Literal["eval.run"] """The type of the object. Always "eval.run".""" per_model_usage: List[PerModelUsage] """Usage statistics for each model during the evaluation run.""" per_testing_criteria_results: List[PerTestingCriteriaResult] """Results per testing criteria applied during the evaluation run.""" report_url: str """The URL to the rendered evaluation run report on the UI dashboard.""" result_counts: ResultCounts """Counters summarizing the outcomes of the evaluation run.""" status: str """The status of the evaluation run.""" ================================================ FILE: src/openai/types/evals/run_retrieve_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo from ..._utils import PropertyInfo from ..._models import BaseModel from .eval_api_error import EvalAPIError from ..responses.tool import Tool from ..shared.metadata import Metadata from ..graders.grader_inputs import GraderInputs from ..shared.reasoning_effort import ReasoningEffort from ..responses.response_input_text import ResponseInputText from ..responses.response_input_audio import ResponseInputAudio from .create_eval_jsonl_run_data_source import CreateEvalJSONLRunDataSource from ..responses.response_format_text_config import ResponseFormatTextConfig from .create_eval_completions_run_data_source import CreateEvalCompletionsRunDataSource __all__ = [ "RunRetrieveResponse", "DataSource", "DataSourceResponses", "DataSourceResponsesSource", "DataSourceResponsesSourceFileContent", "DataSourceResponsesSourceFileContentContent", "DataSourceResponsesSourceFileID", "DataSourceResponsesSourceResponses", "DataSourceResponsesInputMessages", "DataSourceResponsesInputMessagesTemplate", "DataSourceResponsesInputMessagesTemplateTemplate", "DataSourceResponsesInputMessagesTemplateTemplateChatMessage", "DataSourceResponsesInputMessagesTemplateTemplateEvalItem", "DataSourceResponsesInputMessagesTemplateTemplateEvalItemContent", "DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentOutputText", "DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentInputImage", "DataSourceResponsesInputMessagesItemReference", "DataSourceResponsesSamplingParams", "DataSourceResponsesSamplingParamsText", "PerModelUsage", "PerTestingCriteriaResult", "ResultCounts", ] class DataSourceResponsesSourceFileContentContent(BaseModel): item: Dict[str, object] sample: Optional[Dict[str, object]] = None class DataSourceResponsesSourceFileContent(BaseModel): content: List[DataSourceResponsesSourceFileContentContent] """The content of the jsonl file.""" type: Literal["file_content"] """The type of jsonl source. Always `file_content`.""" class DataSourceResponsesSourceFileID(BaseModel): id: str """The identifier of the file.""" type: Literal["file_id"] """The type of jsonl source. Always `file_id`.""" class DataSourceResponsesSourceResponses(BaseModel): """A EvalResponsesSource object describing a run data source configuration.""" type: Literal["responses"] """The type of run data source. Always `responses`.""" created_after: Optional[int] = None """Only include items created after this timestamp (inclusive). This is a query parameter used to select responses. """ created_before: Optional[int] = None """Only include items created before this timestamp (inclusive). This is a query parameter used to select responses. """ instructions_search: Optional[str] = None """Optional string to search the 'instructions' field. This is a query parameter used to select responses. """ metadata: Optional[object] = None """Metadata filter for the responses. This is a query parameter used to select responses. """ model: Optional[str] = None """The name of the model to find responses for. This is a query parameter used to select responses. """ reasoning_effort: Optional[ReasoningEffort] = None """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ temperature: Optional[float] = None """Sampling temperature. This is a query parameter used to select responses.""" tools: Optional[List[str]] = None """List of tool names. This is a query parameter used to select responses.""" top_p: Optional[float] = None """Nucleus sampling parameter. This is a query parameter used to select responses.""" users: Optional[List[str]] = None """List of user identifiers. This is a query parameter used to select responses.""" DataSourceResponsesSource: TypeAlias = Annotated[ Union[DataSourceResponsesSourceFileContent, DataSourceResponsesSourceFileID, DataSourceResponsesSourceResponses], PropertyInfo(discriminator="type"), ] class DataSourceResponsesInputMessagesTemplateTemplateChatMessage(BaseModel): content: str """The content of the message.""" role: str """The role of the message (e.g. "system", "assistant", "user").""" class DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentOutputText(BaseModel): """A text output from the model.""" text: str """The text output from the model.""" type: Literal["output_text"] """The type of the output text. Always `output_text`.""" class DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentInputImage(BaseModel): """An image input block used within EvalItem content arrays.""" image_url: str """The URL of the image input.""" type: Literal["input_image"] """The type of the image input. Always `input_image`.""" detail: Optional[str] = None """The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. Defaults to `auto`. """ DataSourceResponsesInputMessagesTemplateTemplateEvalItemContent: TypeAlias = Union[ str, ResponseInputText, DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentOutputText, DataSourceResponsesInputMessagesTemplateTemplateEvalItemContentInputImage, ResponseInputAudio, GraderInputs, ] class DataSourceResponsesInputMessagesTemplateTemplateEvalItem(BaseModel): """ A message input to the model with a role indicating instruction following hierarchy. Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role. Messages with the `assistant` role are presumed to have been generated by the model in previous interactions. """ content: DataSourceResponsesInputMessagesTemplateTemplateEvalItemContent """Inputs to the model - can contain template strings. Supports text, output text, input images, and input audio, either as a single item or an array of items. """ role: Literal["user", "assistant", "system", "developer"] """The role of the message input. One of `user`, `assistant`, `system`, or `developer`. """ type: Optional[Literal["message"]] = None """The type of the message input. Always `message`.""" DataSourceResponsesInputMessagesTemplateTemplate: TypeAlias = Union[ DataSourceResponsesInputMessagesTemplateTemplateChatMessage, DataSourceResponsesInputMessagesTemplateTemplateEvalItem, ] class DataSourceResponsesInputMessagesTemplate(BaseModel): template: List[DataSourceResponsesInputMessagesTemplateTemplate] """A list of chat messages forming the prompt or context. May include variable references to the `item` namespace, ie {{item.name}}. """ type: Literal["template"] """The type of input messages. Always `template`.""" class DataSourceResponsesInputMessagesItemReference(BaseModel): item_reference: str """A reference to a variable in the `item` namespace. Ie, "item.name" """ type: Literal["item_reference"] """The type of input messages. Always `item_reference`.""" DataSourceResponsesInputMessages: TypeAlias = Annotated[ Union[DataSourceResponsesInputMessagesTemplate, DataSourceResponsesInputMessagesItemReference], PropertyInfo(discriminator="type"), ] class DataSourceResponsesSamplingParamsText(BaseModel): """Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) """ format: Optional[ResponseFormatTextConfig] = None """An object specifying the format that the model must output. Configuring `{ "type": "json_schema" }` enables Structured Outputs, which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). The default format is `{ "type": "text" }` with no additional options. **Not recommended for gpt-4o and newer models:** Setting to `{ "type": "json_object" }` enables the older JSON mode, which ensures the message the model generates is valid JSON. Using `json_schema` is preferred for models that support it. """ class DataSourceResponsesSamplingParams(BaseModel): max_completion_tokens: Optional[int] = None """The maximum number of tokens in the generated output.""" reasoning_effort: Optional[ReasoningEffort] = None """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ seed: Optional[int] = None """A seed value to initialize the randomness, during sampling.""" temperature: Optional[float] = None """A higher temperature increases randomness in the outputs.""" text: Optional[DataSourceResponsesSamplingParamsText] = None """Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) """ tools: Optional[List[Tool]] = None """An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. The two categories of tools you can provide the model are: - **Built-in tools**: Tools that are provided by OpenAI that extend the model's capabilities, like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). - **Function calls (custom tools)**: Functions that are defined by you, enabling the model to call your own code. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). """ top_p: Optional[float] = None """An alternative to temperature for nucleus sampling; 1.0 includes all tokens.""" class DataSourceResponses(BaseModel): """A ResponsesRunDataSource object describing a model sampling configuration.""" source: DataSourceResponsesSource """Determines what populates the `item` namespace in this run's data source.""" type: Literal["responses"] """The type of run data source. Always `responses`.""" input_messages: Optional[DataSourceResponsesInputMessages] = None """Used when sampling from a model. Dictates the structure of the messages passed into the model. Can either be a reference to a prebuilt trajectory (ie, `item.input_trajectory`), or a template with variable references to the `item` namespace. """ model: Optional[str] = None """The name of the model to use for generating completions (e.g. "o3-mini").""" sampling_params: Optional[DataSourceResponsesSamplingParams] = None DataSource: TypeAlias = Annotated[ Union[CreateEvalJSONLRunDataSource, CreateEvalCompletionsRunDataSource, DataSourceResponses], PropertyInfo(discriminator="type"), ] class PerModelUsage(BaseModel): cached_tokens: int """The number of tokens retrieved from cache.""" completion_tokens: int """The number of completion tokens generated.""" invocation_count: int """The number of invocations.""" run_model_name: str = FieldInfo(alias="model_name") """The name of the model.""" prompt_tokens: int """The number of prompt tokens used.""" total_tokens: int """The total number of tokens used.""" class PerTestingCriteriaResult(BaseModel): failed: int """Number of tests failed for this criteria.""" passed: int """Number of tests passed for this criteria.""" testing_criteria: str """A description of the testing criteria.""" class ResultCounts(BaseModel): """Counters summarizing the outcomes of the evaluation run.""" errored: int """Number of output items that resulted in an error.""" failed: int """Number of output items that failed to pass the evaluation.""" passed: int """Number of output items that passed the evaluation.""" total: int """Total number of executed output items.""" class RunRetrieveResponse(BaseModel): """A schema representing an evaluation run.""" id: str """Unique identifier for the evaluation run.""" created_at: int """Unix timestamp (in seconds) when the evaluation run was created.""" data_source: DataSource """Information about the run's data source.""" error: EvalAPIError """An object representing an error response from the Eval API.""" eval_id: str """The identifier of the associated evaluation.""" metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ model: str """The model that is evaluated, if applicable.""" name: str """The name of the evaluation run.""" object: Literal["eval.run"] """The type of the object. Always "eval.run".""" per_model_usage: List[PerModelUsage] """Usage statistics for each model during the evaluation run.""" per_testing_criteria_results: List[PerTestingCriteriaResult] """Results per testing criteria applied during the evaluation run.""" report_url: str """The URL to the rendered evaluation run report on the UI dashboard.""" result_counts: ResultCounts """Counters summarizing the outcomes of the evaluation run.""" status: str """The status of the evaluation run.""" ================================================ FILE: src/openai/types/evals/runs/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .output_item_list_params import OutputItemListParams as OutputItemListParams from .output_item_list_response import OutputItemListResponse as OutputItemListResponse from .output_item_retrieve_response import OutputItemRetrieveResponse as OutputItemRetrieveResponse ================================================ FILE: src/openai/types/evals/runs/output_item_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["OutputItemListParams"] class OutputItemListParams(TypedDict, total=False): eval_id: Required[str] after: str """Identifier for the last output item from the previous pagination request.""" limit: int """Number of output items to retrieve.""" order: Literal["asc", "desc"] """Sort order for output items by timestamp. Use `asc` for ascending order or `desc` for descending order. Defaults to `asc`. """ status: Literal["fail", "pass"] """Filter output items by status. Use `failed` to filter by failed output items or `pass` to filter by passed output items. """ ================================================ FILE: src/openai/types/evals/runs/output_item_list_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import TYPE_CHECKING, Dict, List, Optional from typing_extensions import Literal from pydantic import Field as FieldInfo from ...._models import BaseModel from ..eval_api_error import EvalAPIError __all__ = ["OutputItemListResponse", "Result", "Sample", "SampleInput", "SampleOutput", "SampleUsage"] class Result(BaseModel): """A single grader result for an evaluation run output item.""" name: str """The name of the grader.""" passed: bool """Whether the grader considered the output a pass.""" score: float """The numeric score produced by the grader.""" sample: Optional[Dict[str, object]] = None """Optional sample or intermediate data produced by the grader.""" type: Optional[str] = None """The grader type (for example, "string-check-grader").""" if TYPE_CHECKING: # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a # value to this field, so for compatibility we avoid doing it at runtime. __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] # Stub to indicate that arbitrary properties are accepted. # To access properties that are not valid identifiers you can use `getattr`, e.g. # `getattr(obj, '$type')` def __getattr__(self, attr: str) -> object: ... else: __pydantic_extra__: Dict[str, object] class SampleInput(BaseModel): """An input message.""" content: str """The content of the message.""" role: str """The role of the message sender (e.g., system, user, developer).""" class SampleOutput(BaseModel): content: Optional[str] = None """The content of the message.""" role: Optional[str] = None """The role of the message (e.g. "system", "assistant", "user").""" class SampleUsage(BaseModel): """Token usage details for the sample.""" cached_tokens: int """The number of tokens retrieved from cache.""" completion_tokens: int """The number of completion tokens generated.""" prompt_tokens: int """The number of prompt tokens used.""" total_tokens: int """The total number of tokens used.""" class Sample(BaseModel): """A sample containing the input and output of the evaluation run.""" error: EvalAPIError """An object representing an error response from the Eval API.""" finish_reason: str """The reason why the sample generation was finished.""" input: List[SampleInput] """An array of input messages.""" max_completion_tokens: int """The maximum number of tokens allowed for completion.""" model: str """The model used for generating the sample.""" output: List[SampleOutput] """An array of output messages.""" seed: int """The seed used for generating the sample.""" temperature: float """The sampling temperature used.""" top_p: float """The top_p value used for sampling.""" usage: SampleUsage """Token usage details for the sample.""" class OutputItemListResponse(BaseModel): """A schema representing an evaluation run output item.""" id: str """Unique identifier for the evaluation run output item.""" created_at: int """Unix timestamp (in seconds) when the evaluation run was created.""" datasource_item: Dict[str, object] """Details of the input data source item.""" datasource_item_id: int """The identifier for the data source item.""" eval_id: str """The identifier of the evaluation group.""" object: Literal["eval.run.output_item"] """The type of the object. Always "eval.run.output_item".""" results: List[Result] """A list of grader results for this output item.""" run_id: str """The identifier of the evaluation run associated with this output item.""" sample: Sample """A sample containing the input and output of the evaluation run.""" status: str """The status of the evaluation run.""" ================================================ FILE: src/openai/types/evals/runs/output_item_retrieve_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import TYPE_CHECKING, Dict, List, Optional from typing_extensions import Literal from pydantic import Field as FieldInfo from ...._models import BaseModel from ..eval_api_error import EvalAPIError __all__ = ["OutputItemRetrieveResponse", "Result", "Sample", "SampleInput", "SampleOutput", "SampleUsage"] class Result(BaseModel): """A single grader result for an evaluation run output item.""" name: str """The name of the grader.""" passed: bool """Whether the grader considered the output a pass.""" score: float """The numeric score produced by the grader.""" sample: Optional[Dict[str, object]] = None """Optional sample or intermediate data produced by the grader.""" type: Optional[str] = None """The grader type (for example, "string-check-grader").""" if TYPE_CHECKING: # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a # value to this field, so for compatibility we avoid doing it at runtime. __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] # Stub to indicate that arbitrary properties are accepted. # To access properties that are not valid identifiers you can use `getattr`, e.g. # `getattr(obj, '$type')` def __getattr__(self, attr: str) -> object: ... else: __pydantic_extra__: Dict[str, object] class SampleInput(BaseModel): """An input message.""" content: str """The content of the message.""" role: str """The role of the message sender (e.g., system, user, developer).""" class SampleOutput(BaseModel): content: Optional[str] = None """The content of the message.""" role: Optional[str] = None """The role of the message (e.g. "system", "assistant", "user").""" class SampleUsage(BaseModel): """Token usage details for the sample.""" cached_tokens: int """The number of tokens retrieved from cache.""" completion_tokens: int """The number of completion tokens generated.""" prompt_tokens: int """The number of prompt tokens used.""" total_tokens: int """The total number of tokens used.""" class Sample(BaseModel): """A sample containing the input and output of the evaluation run.""" error: EvalAPIError """An object representing an error response from the Eval API.""" finish_reason: str """The reason why the sample generation was finished.""" input: List[SampleInput] """An array of input messages.""" max_completion_tokens: int """The maximum number of tokens allowed for completion.""" model: str """The model used for generating the sample.""" output: List[SampleOutput] """An array of output messages.""" seed: int """The seed used for generating the sample.""" temperature: float """The sampling temperature used.""" top_p: float """The top_p value used for sampling.""" usage: SampleUsage """Token usage details for the sample.""" class OutputItemRetrieveResponse(BaseModel): """A schema representing an evaluation run output item.""" id: str """Unique identifier for the evaluation run output item.""" created_at: int """Unix timestamp (in seconds) when the evaluation run was created.""" datasource_item: Dict[str, object] """Details of the input data source item.""" datasource_item_id: int """The identifier for the data source item.""" eval_id: str """The identifier of the evaluation group.""" object: Literal["eval.run.output_item"] """The type of the object. Always "eval.run.output_item".""" results: List[Result] """A list of grader results for this output item.""" run_id: str """The identifier of the evaluation run associated with this output item.""" sample: Sample """A sample containing the input and output of the evaluation run.""" status: str """The status of the evaluation run.""" ================================================ FILE: src/openai/types/file_chunking_strategy.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from .._utils import PropertyInfo from .other_file_chunking_strategy_object import OtherFileChunkingStrategyObject from .static_file_chunking_strategy_object import StaticFileChunkingStrategyObject __all__ = ["FileChunkingStrategy"] FileChunkingStrategy: TypeAlias = Annotated[ Union[StaticFileChunkingStrategyObject, OtherFileChunkingStrategyObject], PropertyInfo(discriminator="type") ] ================================================ FILE: src/openai/types/file_chunking_strategy_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import TypeAlias from .auto_file_chunking_strategy_param import AutoFileChunkingStrategyParam from .static_file_chunking_strategy_object_param import StaticFileChunkingStrategyObjectParam __all__ = ["FileChunkingStrategyParam"] FileChunkingStrategyParam: TypeAlias = Union[AutoFileChunkingStrategyParam, StaticFileChunkingStrategyObjectParam] ================================================ FILE: src/openai/types/file_content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import TypeAlias __all__ = ["FileContent"] FileContent: TypeAlias = str ================================================ FILE: src/openai/types/file_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict from .._types import FileTypes from .file_purpose import FilePurpose __all__ = ["FileCreateParams", "ExpiresAfter"] class FileCreateParams(TypedDict, total=False): file: Required[FileTypes] """The File object (not file name) to be uploaded.""" purpose: Required[FilePurpose] """The intended purpose of the uploaded file. One of: - `assistants`: Used in the Assistants API - `batch`: Used in the Batch API - `fine-tune`: Used for fine-tuning - `vision`: Images used for vision fine-tuning - `user_data`: Flexible file type for any purpose - `evals`: Used for eval data sets """ expires_after: ExpiresAfter """The expiration policy for a file. By default, files with `purpose=batch` expire after 30 days and all other files are persisted until they are manually deleted. """ class ExpiresAfter(TypedDict, total=False): """The expiration policy for a file. By default, files with `purpose=batch` expire after 30 days and all other files are persisted until they are manually deleted. """ anchor: Required[Literal["created_at"]] """Anchor timestamp after which the expiration policy applies. Supported anchors: `created_at`. """ seconds: Required[int] """The number of seconds after the anchor time that the file will expire. Must be between 3600 (1 hour) and 2592000 (30 days). """ ================================================ FILE: src/openai/types/file_deleted.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .._models import BaseModel __all__ = ["FileDeleted"] class FileDeleted(BaseModel): id: str deleted: bool object: Literal["file"] ================================================ FILE: src/openai/types/file_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["FileListParams"] class FileListParams(TypedDict, total=False): after: str """A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. """ limit: int """A limit on the number of objects to be returned. Limit can range between 1 and 10,000, and the default is 10,000. """ order: Literal["asc", "desc"] """Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. """ purpose: str """Only return files with the given purpose.""" ================================================ FILE: src/openai/types/file_object.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from .._models import BaseModel __all__ = ["FileObject"] class FileObject(BaseModel): """The `File` object represents a document that has been uploaded to OpenAI.""" id: str """The file identifier, which can be referenced in the API endpoints.""" bytes: int """The size of the file, in bytes.""" created_at: int """The Unix timestamp (in seconds) for when the file was created.""" filename: str """The name of the file.""" object: Literal["file"] """The object type, which is always `file`.""" purpose: Literal[ "assistants", "assistants_output", "batch", "batch_output", "fine-tune", "fine-tune-results", "vision", "user_data", ] """The intended purpose of the file. Supported values are `assistants`, `assistants_output`, `batch`, `batch_output`, `fine-tune`, `fine-tune-results`, `vision`, and `user_data`. """ status: Literal["uploaded", "processed", "error"] """Deprecated. The current status of the file, which can be either `uploaded`, `processed`, or `error`. """ expires_at: Optional[int] = None """The Unix timestamp (in seconds) for when the file will expire.""" status_details: Optional[str] = None """Deprecated. For details on why a fine-tuning training file failed validation, see the `error` field on `fine_tuning.job`. """ ================================================ FILE: src/openai/types/file_purpose.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["FilePurpose"] FilePurpose: TypeAlias = Literal["assistants", "batch", "fine-tune", "vision", "user_data", "evals"] ================================================ FILE: src/openai/types/fine_tuning/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .dpo_method import DpoMethod as DpoMethod from .fine_tuning_job import FineTuningJob as FineTuningJob from .job_list_params import JobListParams as JobListParams from .dpo_method_param import DpoMethodParam as DpoMethodParam from .job_create_params import JobCreateParams as JobCreateParams from .supervised_method import SupervisedMethod as SupervisedMethod from .dpo_hyperparameters import DpoHyperparameters as DpoHyperparameters from .reinforcement_method import ReinforcementMethod as ReinforcementMethod from .fine_tuning_job_event import FineTuningJobEvent as FineTuningJobEvent from .job_list_events_params import JobListEventsParams as JobListEventsParams from .supervised_method_param import SupervisedMethodParam as SupervisedMethodParam from .dpo_hyperparameters_param import DpoHyperparametersParam as DpoHyperparametersParam from .reinforcement_method_param import ReinforcementMethodParam as ReinforcementMethodParam from .supervised_hyperparameters import SupervisedHyperparameters as SupervisedHyperparameters from .fine_tuning_job_integration import FineTuningJobIntegration as FineTuningJobIntegration from .reinforcement_hyperparameters import ReinforcementHyperparameters as ReinforcementHyperparameters from .supervised_hyperparameters_param import SupervisedHyperparametersParam as SupervisedHyperparametersParam from .fine_tuning_job_wandb_integration import FineTuningJobWandbIntegration as FineTuningJobWandbIntegration from .reinforcement_hyperparameters_param import ReinforcementHyperparametersParam as ReinforcementHyperparametersParam from .fine_tuning_job_wandb_integration_object import ( FineTuningJobWandbIntegrationObject as FineTuningJobWandbIntegrationObject, ) ================================================ FILE: src/openai/types/fine_tuning/alpha/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .grader_run_params import GraderRunParams as GraderRunParams from .grader_run_response import GraderRunResponse as GraderRunResponse from .grader_validate_params import GraderValidateParams as GraderValidateParams from .grader_validate_response import GraderValidateResponse as GraderValidateResponse ================================================ FILE: src/openai/types/fine_tuning/alpha/grader_run_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Required, TypeAlias, TypedDict from ...graders.multi_grader_param import MultiGraderParam from ...graders.python_grader_param import PythonGraderParam from ...graders.score_model_grader_param import ScoreModelGraderParam from ...graders.string_check_grader_param import StringCheckGraderParam from ...graders.text_similarity_grader_param import TextSimilarityGraderParam __all__ = ["GraderRunParams", "Grader"] class GraderRunParams(TypedDict, total=False): grader: Required[Grader] """The grader used for the fine-tuning job.""" model_sample: Required[str] """The model sample to be evaluated. This value will be used to populate the `sample` namespace. See [the guide](https://platform.openai.com/docs/guides/graders) for more details. The `output_json` variable will be populated if the model sample is a valid JSON string. """ item: object """The dataset item provided to the grader. This will be used to populate the `item` namespace. See [the guide](https://platform.openai.com/docs/guides/graders) for more details. """ Grader: TypeAlias = Union[ StringCheckGraderParam, TextSimilarityGraderParam, PythonGraderParam, ScoreModelGraderParam, MultiGraderParam ] ================================================ FILE: src/openai/types/fine_tuning/alpha/grader_run_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, Optional from pydantic import Field as FieldInfo from ...._models import BaseModel __all__ = ["GraderRunResponse", "Metadata", "MetadataErrors"] class MetadataErrors(BaseModel): formula_parse_error: bool invalid_variable_error: bool api_model_grader_parse_error: bool = FieldInfo(alias="model_grader_parse_error") api_model_grader_refusal_error: bool = FieldInfo(alias="model_grader_refusal_error") api_model_grader_server_error: bool = FieldInfo(alias="model_grader_server_error") api_model_grader_server_error_details: Optional[str] = FieldInfo( alias="model_grader_server_error_details", default=None ) other_error: bool python_grader_runtime_error: bool python_grader_runtime_error_details: Optional[str] = None python_grader_server_error: bool python_grader_server_error_type: Optional[str] = None sample_parse_error: bool truncated_observation_error: bool unresponsive_reward_error: bool class Metadata(BaseModel): errors: MetadataErrors execution_time: float name: str sampled_model_name: Optional[str] = None scores: Dict[str, object] token_usage: Optional[int] = None type: str class GraderRunResponse(BaseModel): metadata: Metadata api_model_grader_token_usage_per_model: Dict[str, object] = FieldInfo(alias="model_grader_token_usage_per_model") reward: float sub_rewards: Dict[str, object] ================================================ FILE: src/openai/types/fine_tuning/alpha/grader_validate_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Required, TypeAlias, TypedDict from ...graders.multi_grader_param import MultiGraderParam from ...graders.python_grader_param import PythonGraderParam from ...graders.score_model_grader_param import ScoreModelGraderParam from ...graders.string_check_grader_param import StringCheckGraderParam from ...graders.text_similarity_grader_param import TextSimilarityGraderParam __all__ = ["GraderValidateParams", "Grader"] class GraderValidateParams(TypedDict, total=False): grader: Required[Grader] """The grader used for the fine-tuning job.""" Grader: TypeAlias = Union[ StringCheckGraderParam, TextSimilarityGraderParam, PythonGraderParam, ScoreModelGraderParam, MultiGraderParam ] ================================================ FILE: src/openai/types/fine_tuning/alpha/grader_validate_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import TypeAlias from ...._models import BaseModel from ...graders.multi_grader import MultiGrader from ...graders.python_grader import PythonGrader from ...graders.score_model_grader import ScoreModelGrader from ...graders.string_check_grader import StringCheckGrader from ...graders.text_similarity_grader import TextSimilarityGrader __all__ = ["GraderValidateResponse", "Grader"] Grader: TypeAlias = Union[StringCheckGrader, TextSimilarityGrader, PythonGrader, ScoreModelGrader, MultiGrader] class GraderValidateResponse(BaseModel): grader: Optional[Grader] = None """The grader used for the fine-tuning job.""" ================================================ FILE: src/openai/types/fine_tuning/checkpoints/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .permission_list_params import PermissionListParams as PermissionListParams from .permission_create_params import PermissionCreateParams as PermissionCreateParams from .permission_list_response import PermissionListResponse as PermissionListResponse from .permission_create_response import PermissionCreateResponse as PermissionCreateResponse from .permission_delete_response import PermissionDeleteResponse as PermissionDeleteResponse from .permission_retrieve_params import PermissionRetrieveParams as PermissionRetrieveParams from .permission_retrieve_response import PermissionRetrieveResponse as PermissionRetrieveResponse ================================================ FILE: src/openai/types/fine_tuning/checkpoints/permission_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Required, TypedDict from ...._types import SequenceNotStr __all__ = ["PermissionCreateParams"] class PermissionCreateParams(TypedDict, total=False): project_ids: Required[SequenceNotStr[str]] """The project identifiers to grant access to.""" ================================================ FILE: src/openai/types/fine_tuning/checkpoints/permission_create_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["PermissionCreateResponse"] class PermissionCreateResponse(BaseModel): """ The `checkpoint.permission` object represents a permission for a fine-tuned model checkpoint. """ id: str """The permission identifier, which can be referenced in the API endpoints.""" created_at: int """The Unix timestamp (in seconds) for when the permission was created.""" object: Literal["checkpoint.permission"] """The object type, which is always "checkpoint.permission".""" project_id: str """The project identifier that the permission is for.""" ================================================ FILE: src/openai/types/fine_tuning/checkpoints/permission_delete_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["PermissionDeleteResponse"] class PermissionDeleteResponse(BaseModel): id: str """The ID of the fine-tuned model checkpoint permission that was deleted.""" deleted: bool """Whether the fine-tuned model checkpoint permission was successfully deleted.""" object: Literal["checkpoint.permission"] """The object type, which is always "checkpoint.permission".""" ================================================ FILE: src/openai/types/fine_tuning/checkpoints/permission_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["PermissionListParams"] class PermissionListParams(TypedDict, total=False): after: str """Identifier for the last permission ID from the previous pagination request.""" limit: int """Number of permissions to retrieve.""" order: Literal["ascending", "descending"] """The order in which to retrieve permissions.""" project_id: str """The ID of the project to get permissions for.""" ================================================ FILE: src/openai/types/fine_tuning/checkpoints/permission_list_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ...._models import BaseModel __all__ = ["PermissionListResponse"] class PermissionListResponse(BaseModel): """ The `checkpoint.permission` object represents a permission for a fine-tuned model checkpoint. """ id: str """The permission identifier, which can be referenced in the API endpoints.""" created_at: int """The Unix timestamp (in seconds) for when the permission was created.""" object: Literal["checkpoint.permission"] """The object type, which is always "checkpoint.permission".""" project_id: str """The project identifier that the permission is for.""" ================================================ FILE: src/openai/types/fine_tuning/checkpoints/permission_retrieve_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["PermissionRetrieveParams"] class PermissionRetrieveParams(TypedDict, total=False): after: str """Identifier for the last permission ID from the previous pagination request.""" limit: int """Number of permissions to retrieve.""" order: Literal["ascending", "descending"] """The order in which to retrieve permissions.""" project_id: str """The ID of the project to get permissions for.""" ================================================ FILE: src/openai/types/fine_tuning/checkpoints/permission_retrieve_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["PermissionRetrieveResponse", "Data"] class Data(BaseModel): """ The `checkpoint.permission` object represents a permission for a fine-tuned model checkpoint. """ id: str """The permission identifier, which can be referenced in the API endpoints.""" created_at: int """The Unix timestamp (in seconds) for when the permission was created.""" object: Literal["checkpoint.permission"] """The object type, which is always "checkpoint.permission".""" project_id: str """The project identifier that the permission is for.""" class PermissionRetrieveResponse(BaseModel): data: List[Data] has_more: bool object: Literal["list"] first_id: Optional[str] = None last_id: Optional[str] = None ================================================ FILE: src/openai/types/fine_tuning/dpo_hyperparameters.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Literal from ..._models import BaseModel __all__ = ["DpoHyperparameters"] class DpoHyperparameters(BaseModel): """The hyperparameters used for the DPO fine-tuning job.""" batch_size: Union[Literal["auto"], int, None] = None """Number of examples in each batch. A larger batch size means that model parameters are updated less frequently, but with lower variance. """ beta: Union[Literal["auto"], float, None] = None """The beta value for the DPO method. A higher beta value will increase the weight of the penalty between the policy and reference model. """ learning_rate_multiplier: Union[Literal["auto"], float, None] = None """Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting. """ n_epochs: Union[Literal["auto"], int, None] = None """The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. """ ================================================ FILE: src/openai/types/fine_tuning/dpo_hyperparameters_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, TypedDict __all__ = ["DpoHyperparametersParam"] class DpoHyperparametersParam(TypedDict, total=False): """The hyperparameters used for the DPO fine-tuning job.""" batch_size: Union[Literal["auto"], int] """Number of examples in each batch. A larger batch size means that model parameters are updated less frequently, but with lower variance. """ beta: Union[Literal["auto"], float] """The beta value for the DPO method. A higher beta value will increase the weight of the penalty between the policy and reference model. """ learning_rate_multiplier: Union[Literal["auto"], float] """Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting. """ n_epochs: Union[Literal["auto"], int] """The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. """ ================================================ FILE: src/openai/types/fine_tuning/dpo_method.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from ..._models import BaseModel from .dpo_hyperparameters import DpoHyperparameters __all__ = ["DpoMethod"] class DpoMethod(BaseModel): """Configuration for the DPO fine-tuning method.""" hyperparameters: Optional[DpoHyperparameters] = None """The hyperparameters used for the DPO fine-tuning job.""" ================================================ FILE: src/openai/types/fine_tuning/dpo_method_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import TypedDict from .dpo_hyperparameters_param import DpoHyperparametersParam __all__ = ["DpoMethodParam"] class DpoMethodParam(TypedDict, total=False): """Configuration for the DPO fine-tuning method.""" hyperparameters: DpoHyperparametersParam """The hyperparameters used for the DPO fine-tuning job.""" ================================================ FILE: src/openai/types/fine_tuning/fine_tuning_job.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal from ..._models import BaseModel from .dpo_method import DpoMethod from ..shared.metadata import Metadata from .supervised_method import SupervisedMethod from .reinforcement_method import ReinforcementMethod from .fine_tuning_job_wandb_integration_object import FineTuningJobWandbIntegrationObject __all__ = ["FineTuningJob", "Error", "Hyperparameters", "Method"] class Error(BaseModel): """ For fine-tuning jobs that have `failed`, this will contain more information on the cause of the failure. """ code: str """A machine-readable error code.""" message: str """A human-readable error message.""" param: Optional[str] = None """The parameter that was invalid, usually `training_file` or `validation_file`. This field will be null if the failure was not parameter-specific. """ class Hyperparameters(BaseModel): """The hyperparameters used for the fine-tuning job. This value will only be returned when running `supervised` jobs. """ batch_size: Union[Literal["auto"], int, None] = None """Number of examples in each batch. A larger batch size means that model parameters are updated less frequently, but with lower variance. """ learning_rate_multiplier: Union[Literal["auto"], float, None] = None """Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting. """ n_epochs: Union[Literal["auto"], int, None] = None """The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. """ class Method(BaseModel): """The method used for fine-tuning.""" type: Literal["supervised", "dpo", "reinforcement"] """The type of method. Is either `supervised`, `dpo`, or `reinforcement`.""" dpo: Optional[DpoMethod] = None """Configuration for the DPO fine-tuning method.""" reinforcement: Optional[ReinforcementMethod] = None """Configuration for the reinforcement fine-tuning method.""" supervised: Optional[SupervisedMethod] = None """Configuration for the supervised fine-tuning method.""" class FineTuningJob(BaseModel): """ The `fine_tuning.job` object represents a fine-tuning job that has been created through the API. """ id: str """The object identifier, which can be referenced in the API endpoints.""" created_at: int """The Unix timestamp (in seconds) for when the fine-tuning job was created.""" error: Optional[Error] = None """ For fine-tuning jobs that have `failed`, this will contain more information on the cause of the failure. """ fine_tuned_model: Optional[str] = None """The name of the fine-tuned model that is being created. The value will be null if the fine-tuning job is still running. """ finished_at: Optional[int] = None """The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be null if the fine-tuning job is still running. """ hyperparameters: Hyperparameters """The hyperparameters used for the fine-tuning job. This value will only be returned when running `supervised` jobs. """ model: str """The base model that is being fine-tuned.""" object: Literal["fine_tuning.job"] """The object type, which is always "fine_tuning.job".""" organization_id: str """The organization that owns the fine-tuning job.""" result_files: List[str] """The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the [Files API](https://platform.openai.com/docs/api-reference/files/retrieve-contents). """ seed: int """The seed used for the fine-tuning job.""" status: Literal["validating_files", "queued", "running", "succeeded", "failed", "cancelled"] """ The current status of the fine-tuning job, which can be either `validating_files`, `queued`, `running`, `succeeded`, `failed`, or `cancelled`. """ trained_tokens: Optional[int] = None """The total number of billable tokens processed by this fine-tuning job. The value will be null if the fine-tuning job is still running. """ training_file: str """The file ID used for training. You can retrieve the training data with the [Files API](https://platform.openai.com/docs/api-reference/files/retrieve-contents). """ validation_file: Optional[str] = None """The file ID used for validation. You can retrieve the validation results with the [Files API](https://platform.openai.com/docs/api-reference/files/retrieve-contents). """ estimated_finish: Optional[int] = None """ The Unix timestamp (in seconds) for when the fine-tuning job is estimated to finish. The value will be null if the fine-tuning job is not running. """ integrations: Optional[List[FineTuningJobWandbIntegrationObject]] = None """A list of integrations to enable for this fine-tuning job.""" metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ method: Optional[Method] = None """The method used for fine-tuning.""" ================================================ FILE: src/openai/types/fine_tuning/fine_tuning_job_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import builtins from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["FineTuningJobEvent"] class FineTuningJobEvent(BaseModel): """Fine-tuning job event object""" id: str """The object identifier.""" created_at: int """The Unix timestamp (in seconds) for when the fine-tuning job was created.""" level: Literal["info", "warn", "error"] """The log level of the event.""" message: str """The message of the event.""" object: Literal["fine_tuning.job.event"] """The object type, which is always "fine_tuning.job.event".""" data: Optional[builtins.object] = None """The data associated with the event.""" type: Optional[Literal["message", "metrics"]] = None """The type of event.""" ================================================ FILE: src/openai/types/fine_tuning/fine_tuning_job_integration.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .fine_tuning_job_wandb_integration_object import FineTuningJobWandbIntegrationObject FineTuningJobIntegration = FineTuningJobWandbIntegrationObject ================================================ FILE: src/openai/types/fine_tuning/fine_tuning_job_wandb_integration.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from ..._models import BaseModel __all__ = ["FineTuningJobWandbIntegration"] class FineTuningJobWandbIntegration(BaseModel): """The settings for your integration with Weights and Biases. This payload specifies the project that metrics will be sent to. Optionally, you can set an explicit display name for your run, add tags to your run, and set a default entity (team, username, etc) to be associated with your run. """ project: str """The name of the project that the new run will be created under.""" entity: Optional[str] = None """The entity to use for the run. This allows you to set the team or username of the WandB user that you would like associated with the run. If not set, the default entity for the registered WandB API key is used. """ name: Optional[str] = None """A display name to set for the run. If not set, we will use the Job ID as the name. """ tags: Optional[List[str]] = None """A list of tags to be attached to the newly created run. These tags are passed through directly to WandB. Some default tags are generated by OpenAI: "openai/finetune", "openai/{base-model}", "openai/{ftjob-abcdef}". """ ================================================ FILE: src/openai/types/fine_tuning/fine_tuning_job_wandb_integration_object.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel from .fine_tuning_job_wandb_integration import FineTuningJobWandbIntegration __all__ = ["FineTuningJobWandbIntegrationObject"] class FineTuningJobWandbIntegrationObject(BaseModel): type: Literal["wandb"] """The type of the integration being enabled for the fine-tuning job""" wandb: FineTuningJobWandbIntegration """The settings for your integration with Weights and Biases. This payload specifies the project that metrics will be sent to. Optionally, you can set an explicit display name for your run, add tags to your run, and set a default entity (team, username, etc) to be associated with your run. """ ================================================ FILE: src/openai/types/fine_tuning/job_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable, Optional from typing_extensions import Literal, Required, TypedDict from ..._types import SequenceNotStr from .dpo_method_param import DpoMethodParam from ..shared_params.metadata import Metadata from .supervised_method_param import SupervisedMethodParam from .reinforcement_method_param import ReinforcementMethodParam __all__ = ["JobCreateParams", "Hyperparameters", "Integration", "IntegrationWandb", "Method"] class JobCreateParams(TypedDict, total=False): model: Required[Union[str, Literal["babbage-002", "davinci-002", "gpt-3.5-turbo", "gpt-4o-mini"]]] """The name of the model to fine-tune. You can select one of the [supported models](https://platform.openai.com/docs/guides/fine-tuning#which-models-can-be-fine-tuned). """ training_file: Required[str] """The ID of an uploaded file that contains training data. See [upload file](https://platform.openai.com/docs/api-reference/files/create) for how to upload a file. Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with the purpose `fine-tune`. The contents of the file should differ depending on if the model uses the [chat](https://platform.openai.com/docs/api-reference/fine-tuning/chat-input), [completions](https://platform.openai.com/docs/api-reference/fine-tuning/completions-input) format, or if the fine-tuning method uses the [preference](https://platform.openai.com/docs/api-reference/fine-tuning/preference-input) format. See the [fine-tuning guide](https://platform.openai.com/docs/guides/model-optimization) for more details. """ hyperparameters: Hyperparameters """ The hyperparameters used for the fine-tuning job. This value is now deprecated in favor of `method`, and should be passed in under the `method` parameter. """ integrations: Optional[Iterable[Integration]] """A list of integrations to enable for your fine-tuning job.""" metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ method: Method """The method used for fine-tuning.""" seed: Optional[int] """The seed controls the reproducibility of the job. Passing in the same seed and job parameters should produce the same results, but may differ in rare cases. If a seed is not specified, one will be generated for you. """ suffix: Optional[str] """ A string of up to 64 characters that will be added to your fine-tuned model name. For example, a `suffix` of "custom-model-name" would produce a model name like `ft:gpt-4o-mini:openai:custom-model-name:7p4lURel`. """ validation_file: Optional[str] """The ID of an uploaded file that contains validation data. If you provide this file, the data is used to generate validation metrics periodically during fine-tuning. These metrics can be viewed in the fine-tuning results file. The same data should not be present in both train and validation files. Your dataset must be formatted as a JSONL file. You must upload your file with the purpose `fine-tune`. See the [fine-tuning guide](https://platform.openai.com/docs/guides/model-optimization) for more details. """ class Hyperparameters(TypedDict, total=False): """ The hyperparameters used for the fine-tuning job. This value is now deprecated in favor of `method`, and should be passed in under the `method` parameter. """ batch_size: Union[Literal["auto"], int] """Number of examples in each batch. A larger batch size means that model parameters are updated less frequently, but with lower variance. """ learning_rate_multiplier: Union[Literal["auto"], float] """Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting. """ n_epochs: Union[Literal["auto"], int] """The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. """ class IntegrationWandb(TypedDict, total=False): """The settings for your integration with Weights and Biases. This payload specifies the project that metrics will be sent to. Optionally, you can set an explicit display name for your run, add tags to your run, and set a default entity (team, username, etc) to be associated with your run. """ project: Required[str] """The name of the project that the new run will be created under.""" entity: Optional[str] """The entity to use for the run. This allows you to set the team or username of the WandB user that you would like associated with the run. If not set, the default entity for the registered WandB API key is used. """ name: Optional[str] """A display name to set for the run. If not set, we will use the Job ID as the name. """ tags: SequenceNotStr[str] """A list of tags to be attached to the newly created run. These tags are passed through directly to WandB. Some default tags are generated by OpenAI: "openai/finetune", "openai/{base-model}", "openai/{ftjob-abcdef}". """ class Integration(TypedDict, total=False): type: Required[Literal["wandb"]] """The type of integration to enable. Currently, only "wandb" (Weights and Biases) is supported. """ wandb: Required[IntegrationWandb] """The settings for your integration with Weights and Biases. This payload specifies the project that metrics will be sent to. Optionally, you can set an explicit display name for your run, add tags to your run, and set a default entity (team, username, etc) to be associated with your run. """ class Method(TypedDict, total=False): """The method used for fine-tuning.""" type: Required[Literal["supervised", "dpo", "reinforcement"]] """The type of method. Is either `supervised`, `dpo`, or `reinforcement`.""" dpo: DpoMethodParam """Configuration for the DPO fine-tuning method.""" reinforcement: ReinforcementMethodParam """Configuration for the reinforcement fine-tuning method.""" supervised: SupervisedMethodParam """Configuration for the supervised fine-tuning method.""" ================================================ FILE: src/openai/types/fine_tuning/job_list_events_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import TypedDict __all__ = ["JobListEventsParams"] class JobListEventsParams(TypedDict, total=False): after: str """Identifier for the last event from the previous pagination request.""" limit: int """Number of events to retrieve.""" ================================================ FILE: src/openai/types/fine_tuning/job_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Optional from typing_extensions import TypedDict __all__ = ["JobListParams"] class JobListParams(TypedDict, total=False): after: str """Identifier for the last job from the previous pagination request.""" limit: int """Number of fine-tuning jobs to retrieve.""" metadata: Optional[Dict[str, str]] """Optional metadata filter. To filter, use the syntax `metadata[k]=v`. Alternatively, set `metadata=null` to indicate no metadata. """ ================================================ FILE: src/openai/types/fine_tuning/jobs/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .checkpoint_list_params import CheckpointListParams as CheckpointListParams from .fine_tuning_job_checkpoint import FineTuningJobCheckpoint as FineTuningJobCheckpoint ================================================ FILE: src/openai/types/fine_tuning/jobs/checkpoint_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import TypedDict __all__ = ["CheckpointListParams"] class CheckpointListParams(TypedDict, total=False): after: str """Identifier for the last checkpoint ID from the previous pagination request.""" limit: int """Number of checkpoints to retrieve.""" ================================================ FILE: src/openai/types/fine_tuning/jobs/fine_tuning_job_checkpoint.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ...._models import BaseModel __all__ = ["FineTuningJobCheckpoint", "Metrics"] class Metrics(BaseModel): """Metrics at the step number during the fine-tuning job.""" full_valid_loss: Optional[float] = None full_valid_mean_token_accuracy: Optional[float] = None step: Optional[float] = None train_loss: Optional[float] = None train_mean_token_accuracy: Optional[float] = None valid_loss: Optional[float] = None valid_mean_token_accuracy: Optional[float] = None class FineTuningJobCheckpoint(BaseModel): """ The `fine_tuning.job.checkpoint` object represents a model checkpoint for a fine-tuning job that is ready to use. """ id: str """The checkpoint identifier, which can be referenced in the API endpoints.""" created_at: int """The Unix timestamp (in seconds) for when the checkpoint was created.""" fine_tuned_model_checkpoint: str """The name of the fine-tuned checkpoint model that is created.""" fine_tuning_job_id: str """The name of the fine-tuning job that this checkpoint was created from.""" metrics: Metrics """Metrics at the step number during the fine-tuning job.""" object: Literal["fine_tuning.job.checkpoint"] """The object type, which is always "fine_tuning.job.checkpoint".""" step_number: int """The step number that the checkpoint was created at.""" ================================================ FILE: src/openai/types/fine_tuning/reinforcement_hyperparameters.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ReinforcementHyperparameters"] class ReinforcementHyperparameters(BaseModel): """The hyperparameters used for the reinforcement fine-tuning job.""" batch_size: Union[Literal["auto"], int, None] = None """Number of examples in each batch. A larger batch size means that model parameters are updated less frequently, but with lower variance. """ compute_multiplier: Union[Literal["auto"], float, None] = None """ Multiplier on amount of compute used for exploring search space during training. """ eval_interval: Union[Literal["auto"], int, None] = None """The number of training steps between evaluation runs.""" eval_samples: Union[Literal["auto"], int, None] = None """Number of evaluation samples to generate per training step.""" learning_rate_multiplier: Union[Literal["auto"], float, None] = None """Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting. """ n_epochs: Union[Literal["auto"], int, None] = None """The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. """ reasoning_effort: Optional[Literal["default", "low", "medium", "high"]] = None """Level of reasoning effort.""" ================================================ FILE: src/openai/types/fine_tuning/reinforcement_hyperparameters_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, TypedDict __all__ = ["ReinforcementHyperparametersParam"] class ReinforcementHyperparametersParam(TypedDict, total=False): """The hyperparameters used for the reinforcement fine-tuning job.""" batch_size: Union[Literal["auto"], int] """Number of examples in each batch. A larger batch size means that model parameters are updated less frequently, but with lower variance. """ compute_multiplier: Union[Literal["auto"], float] """ Multiplier on amount of compute used for exploring search space during training. """ eval_interval: Union[Literal["auto"], int] """The number of training steps between evaluation runs.""" eval_samples: Union[Literal["auto"], int] """Number of evaluation samples to generate per training step.""" learning_rate_multiplier: Union[Literal["auto"], float] """Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting. """ n_epochs: Union[Literal["auto"], int] """The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. """ reasoning_effort: Literal["default", "low", "medium", "high"] """Level of reasoning effort.""" ================================================ FILE: src/openai/types/fine_tuning/reinforcement_method.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import TypeAlias from ..._models import BaseModel from ..graders.multi_grader import MultiGrader from ..graders.python_grader import PythonGrader from ..graders.score_model_grader import ScoreModelGrader from ..graders.string_check_grader import StringCheckGrader from .reinforcement_hyperparameters import ReinforcementHyperparameters from ..graders.text_similarity_grader import TextSimilarityGrader __all__ = ["ReinforcementMethod", "Grader"] Grader: TypeAlias = Union[StringCheckGrader, TextSimilarityGrader, PythonGrader, ScoreModelGrader, MultiGrader] class ReinforcementMethod(BaseModel): """Configuration for the reinforcement fine-tuning method.""" grader: Grader """The grader used for the fine-tuning job.""" hyperparameters: Optional[ReinforcementHyperparameters] = None """The hyperparameters used for the reinforcement fine-tuning job.""" ================================================ FILE: src/openai/types/fine_tuning/reinforcement_method_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Required, TypeAlias, TypedDict from ..graders.multi_grader_param import MultiGraderParam from ..graders.python_grader_param import PythonGraderParam from ..graders.score_model_grader_param import ScoreModelGraderParam from ..graders.string_check_grader_param import StringCheckGraderParam from .reinforcement_hyperparameters_param import ReinforcementHyperparametersParam from ..graders.text_similarity_grader_param import TextSimilarityGraderParam __all__ = ["ReinforcementMethodParam", "Grader"] Grader: TypeAlias = Union[ StringCheckGraderParam, TextSimilarityGraderParam, PythonGraderParam, ScoreModelGraderParam, MultiGraderParam ] class ReinforcementMethodParam(TypedDict, total=False): """Configuration for the reinforcement fine-tuning method.""" grader: Required[Grader] """The grader used for the fine-tuning job.""" hyperparameters: ReinforcementHyperparametersParam """The hyperparameters used for the reinforcement fine-tuning job.""" ================================================ FILE: src/openai/types/fine_tuning/supervised_hyperparameters.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Literal from ..._models import BaseModel __all__ = ["SupervisedHyperparameters"] class SupervisedHyperparameters(BaseModel): """The hyperparameters used for the fine-tuning job.""" batch_size: Union[Literal["auto"], int, None] = None """Number of examples in each batch. A larger batch size means that model parameters are updated less frequently, but with lower variance. """ learning_rate_multiplier: Union[Literal["auto"], float, None] = None """Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting. """ n_epochs: Union[Literal["auto"], int, None] = None """The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. """ ================================================ FILE: src/openai/types/fine_tuning/supervised_hyperparameters_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, TypedDict __all__ = ["SupervisedHyperparametersParam"] class SupervisedHyperparametersParam(TypedDict, total=False): """The hyperparameters used for the fine-tuning job.""" batch_size: Union[Literal["auto"], int] """Number of examples in each batch. A larger batch size means that model parameters are updated less frequently, but with lower variance. """ learning_rate_multiplier: Union[Literal["auto"], float] """Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting. """ n_epochs: Union[Literal["auto"], int] """The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. """ ================================================ FILE: src/openai/types/fine_tuning/supervised_method.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from ..._models import BaseModel from .supervised_hyperparameters import SupervisedHyperparameters __all__ = ["SupervisedMethod"] class SupervisedMethod(BaseModel): """Configuration for the supervised fine-tuning method.""" hyperparameters: Optional[SupervisedHyperparameters] = None """The hyperparameters used for the fine-tuning job.""" ================================================ FILE: src/openai/types/fine_tuning/supervised_method_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import TypedDict from .supervised_hyperparameters_param import SupervisedHyperparametersParam __all__ = ["SupervisedMethodParam"] class SupervisedMethodParam(TypedDict, total=False): """Configuration for the supervised fine-tuning method.""" hyperparameters: SupervisedHyperparametersParam """The hyperparameters used for the fine-tuning job.""" ================================================ FILE: src/openai/types/graders/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .multi_grader import MultiGrader as MultiGrader from .grader_inputs import GraderInputs as GraderInputs from .python_grader import PythonGrader as PythonGrader from .label_model_grader import LabelModelGrader as LabelModelGrader from .multi_grader_param import MultiGraderParam as MultiGraderParam from .score_model_grader import ScoreModelGrader as ScoreModelGrader from .grader_inputs_param import GraderInputsParam as GraderInputsParam from .python_grader_param import PythonGraderParam as PythonGraderParam from .string_check_grader import StringCheckGrader as StringCheckGrader from .text_similarity_grader import TextSimilarityGrader as TextSimilarityGrader from .label_model_grader_param import LabelModelGraderParam as LabelModelGraderParam from .score_model_grader_param import ScoreModelGraderParam as ScoreModelGraderParam from .string_check_grader_param import StringCheckGraderParam as StringCheckGraderParam from .text_similarity_grader_param import TextSimilarityGraderParam as TextSimilarityGraderParam ================================================ FILE: src/openai/types/graders/grader_inputs.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, TypeAlias from ..._models import BaseModel from ..responses.response_input_text import ResponseInputText from ..responses.response_input_audio import ResponseInputAudio __all__ = ["GraderInputs", "GraderInputItem", "GraderInputItemOutputText", "GraderInputItemInputImage"] class GraderInputItemOutputText(BaseModel): """A text output from the model.""" text: str """The text output from the model.""" type: Literal["output_text"] """The type of the output text. Always `output_text`.""" class GraderInputItemInputImage(BaseModel): """An image input block used within EvalItem content arrays.""" image_url: str """The URL of the image input.""" type: Literal["input_image"] """The type of the image input. Always `input_image`.""" detail: Optional[str] = None """The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. Defaults to `auto`. """ GraderInputItem: TypeAlias = Union[ str, ResponseInputText, GraderInputItemOutputText, GraderInputItemInputImage, ResponseInputAudio ] GraderInputs: TypeAlias = List[GraderInputItem] ================================================ FILE: src/openai/types/graders/grader_inputs_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List, Union from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..responses.response_input_text_param import ResponseInputTextParam from ..responses.response_input_audio_param import ResponseInputAudioParam __all__ = [ "GraderInputsParam", "GraderInputsParamItem", "GraderInputsParamItemOutputText", "GraderInputsParamItemInputImage", ] class GraderInputsParamItemOutputText(TypedDict, total=False): """A text output from the model.""" text: Required[str] """The text output from the model.""" type: Required[Literal["output_text"]] """The type of the output text. Always `output_text`.""" class GraderInputsParamItemInputImage(TypedDict, total=False): """An image input block used within EvalItem content arrays.""" image_url: Required[str] """The URL of the image input.""" type: Required[Literal["input_image"]] """The type of the image input. Always `input_image`.""" detail: str """The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. Defaults to `auto`. """ GraderInputsParamItem: TypeAlias = Union[ str, ResponseInputTextParam, GraderInputsParamItemOutputText, GraderInputsParamItemInputImage, ResponseInputAudioParam, ] GraderInputsParam: TypeAlias = List[GraderInputsParamItem] ================================================ FILE: src/openai/types/graders/label_model_grader.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, TypeAlias from ..._models import BaseModel from .grader_inputs import GraderInputs from ..responses.response_input_text import ResponseInputText from ..responses.response_input_audio import ResponseInputAudio __all__ = ["LabelModelGrader", "Input", "InputContent", "InputContentOutputText", "InputContentInputImage"] class InputContentOutputText(BaseModel): """A text output from the model.""" text: str """The text output from the model.""" type: Literal["output_text"] """The type of the output text. Always `output_text`.""" class InputContentInputImage(BaseModel): """An image input block used within EvalItem content arrays.""" image_url: str """The URL of the image input.""" type: Literal["input_image"] """The type of the image input. Always `input_image`.""" detail: Optional[str] = None """The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. Defaults to `auto`. """ InputContent: TypeAlias = Union[ str, ResponseInputText, InputContentOutputText, InputContentInputImage, ResponseInputAudio, GraderInputs ] class Input(BaseModel): """ A message input to the model with a role indicating instruction following hierarchy. Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role. Messages with the `assistant` role are presumed to have been generated by the model in previous interactions. """ content: InputContent """Inputs to the model - can contain template strings. Supports text, output text, input images, and input audio, either as a single item or an array of items. """ role: Literal["user", "assistant", "system", "developer"] """The role of the message input. One of `user`, `assistant`, `system`, or `developer`. """ type: Optional[Literal["message"]] = None """The type of the message input. Always `message`.""" class LabelModelGrader(BaseModel): """ A LabelModelGrader object which uses a model to assign labels to each item in the evaluation. """ input: List[Input] labels: List[str] """The labels to assign to each item in the evaluation.""" model: str """The model to use for the evaluation. Must support structured outputs.""" name: str """The name of the grader.""" passing_labels: List[str] """The labels that indicate a passing result. Must be a subset of labels.""" type: Literal["label_model"] """The object type, which is always `label_model`.""" ================================================ FILE: src/openai/types/graders/label_model_grader_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import SequenceNotStr from .grader_inputs_param import GraderInputsParam from ..responses.response_input_text_param import ResponseInputTextParam from ..responses.response_input_audio_param import ResponseInputAudioParam __all__ = ["LabelModelGraderParam", "Input", "InputContent", "InputContentOutputText", "InputContentInputImage"] class InputContentOutputText(TypedDict, total=False): """A text output from the model.""" text: Required[str] """The text output from the model.""" type: Required[Literal["output_text"]] """The type of the output text. Always `output_text`.""" class InputContentInputImage(TypedDict, total=False): """An image input block used within EvalItem content arrays.""" image_url: Required[str] """The URL of the image input.""" type: Required[Literal["input_image"]] """The type of the image input. Always `input_image`.""" detail: str """The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. Defaults to `auto`. """ InputContent: TypeAlias = Union[ str, ResponseInputTextParam, InputContentOutputText, InputContentInputImage, ResponseInputAudioParam, GraderInputsParam, ] class Input(TypedDict, total=False): """ A message input to the model with a role indicating instruction following hierarchy. Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role. Messages with the `assistant` role are presumed to have been generated by the model in previous interactions. """ content: Required[InputContent] """Inputs to the model - can contain template strings. Supports text, output text, input images, and input audio, either as a single item or an array of items. """ role: Required[Literal["user", "assistant", "system", "developer"]] """The role of the message input. One of `user`, `assistant`, `system`, or `developer`. """ type: Literal["message"] """The type of the message input. Always `message`.""" class LabelModelGraderParam(TypedDict, total=False): """ A LabelModelGrader object which uses a model to assign labels to each item in the evaluation. """ input: Required[Iterable[Input]] labels: Required[SequenceNotStr[str]] """The labels to assign to each item in the evaluation.""" model: Required[str] """The model to use for the evaluation. Must support structured outputs.""" name: Required[str] """The name of the grader.""" passing_labels: Required[SequenceNotStr[str]] """The labels that indicate a passing result. Must be a subset of labels.""" type: Required[Literal["label_model"]] """The object type, which is always `label_model`.""" ================================================ FILE: src/openai/types/graders/multi_grader.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Literal, TypeAlias from ..._models import BaseModel from .python_grader import PythonGrader from .label_model_grader import LabelModelGrader from .score_model_grader import ScoreModelGrader from .string_check_grader import StringCheckGrader from .text_similarity_grader import TextSimilarityGrader __all__ = ["MultiGrader", "Graders"] Graders: TypeAlias = Union[StringCheckGrader, TextSimilarityGrader, PythonGrader, ScoreModelGrader, LabelModelGrader] class MultiGrader(BaseModel): """ A MultiGrader object combines the output of multiple graders to produce a single score. """ calculate_output: str """A formula to calculate the output based on grader results.""" graders: Graders """ A StringCheckGrader object that performs a string comparison between input and reference using a specified operation. """ name: str """The name of the grader.""" type: Literal["multi"] """The object type, which is always `multi`.""" ================================================ FILE: src/openai/types/graders/multi_grader_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, Required, TypeAlias, TypedDict from .python_grader_param import PythonGraderParam from .label_model_grader_param import LabelModelGraderParam from .score_model_grader_param import ScoreModelGraderParam from .string_check_grader_param import StringCheckGraderParam from .text_similarity_grader_param import TextSimilarityGraderParam __all__ = ["MultiGraderParam", "Graders"] Graders: TypeAlias = Union[ StringCheckGraderParam, TextSimilarityGraderParam, PythonGraderParam, ScoreModelGraderParam, LabelModelGraderParam ] class MultiGraderParam(TypedDict, total=False): """ A MultiGrader object combines the output of multiple graders to produce a single score. """ calculate_output: Required[str] """A formula to calculate the output based on grader results.""" graders: Required[Graders] """ A StringCheckGrader object that performs a string comparison between input and reference using a specified operation. """ name: Required[str] """The name of the grader.""" type: Required[Literal["multi"]] """The object type, which is always `multi`.""" ================================================ FILE: src/openai/types/graders/python_grader.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["PythonGrader"] class PythonGrader(BaseModel): """A PythonGrader object that runs a python script on the input.""" name: str """The name of the grader.""" source: str """The source code of the python script.""" type: Literal["python"] """The object type, which is always `python`.""" image_tag: Optional[str] = None """The image tag to use for the python script.""" ================================================ FILE: src/openai/types/graders/python_grader_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["PythonGraderParam"] class PythonGraderParam(TypedDict, total=False): """A PythonGrader object that runs a python script on the input.""" name: Required[str] """The name of the grader.""" source: Required[str] """The source code of the python script.""" type: Required[Literal["python"]] """The object type, which is always `python`.""" image_tag: str """The image tag to use for the python script.""" ================================================ FILE: src/openai/types/graders/score_model_grader.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, TypeAlias from ..._models import BaseModel from .grader_inputs import GraderInputs from ..shared.reasoning_effort import ReasoningEffort from ..responses.response_input_text import ResponseInputText from ..responses.response_input_audio import ResponseInputAudio __all__ = [ "ScoreModelGrader", "Input", "InputContent", "InputContentOutputText", "InputContentInputImage", "SamplingParams", ] class InputContentOutputText(BaseModel): """A text output from the model.""" text: str """The text output from the model.""" type: Literal["output_text"] """The type of the output text. Always `output_text`.""" class InputContentInputImage(BaseModel): """An image input block used within EvalItem content arrays.""" image_url: str """The URL of the image input.""" type: Literal["input_image"] """The type of the image input. Always `input_image`.""" detail: Optional[str] = None """The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. Defaults to `auto`. """ InputContent: TypeAlias = Union[ str, ResponseInputText, InputContentOutputText, InputContentInputImage, ResponseInputAudio, GraderInputs ] class Input(BaseModel): """ A message input to the model with a role indicating instruction following hierarchy. Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role. Messages with the `assistant` role are presumed to have been generated by the model in previous interactions. """ content: InputContent """Inputs to the model - can contain template strings. Supports text, output text, input images, and input audio, either as a single item or an array of items. """ role: Literal["user", "assistant", "system", "developer"] """The role of the message input. One of `user`, `assistant`, `system`, or `developer`. """ type: Optional[Literal["message"]] = None """The type of the message input. Always `message`.""" class SamplingParams(BaseModel): """The sampling parameters for the model.""" max_completions_tokens: Optional[int] = None """The maximum number of tokens the grader model may generate in its response.""" reasoning_effort: Optional[ReasoningEffort] = None """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ seed: Optional[int] = None """A seed value to initialize the randomness, during sampling.""" temperature: Optional[float] = None """A higher temperature increases randomness in the outputs.""" top_p: Optional[float] = None """An alternative to temperature for nucleus sampling; 1.0 includes all tokens.""" class ScoreModelGrader(BaseModel): """A ScoreModelGrader object that uses a model to assign a score to the input.""" input: List[Input] """The input messages evaluated by the grader. Supports text, output text, input image, and input audio content blocks, and may include template strings. """ model: str """The model to use for the evaluation.""" name: str """The name of the grader.""" type: Literal["score_model"] """The object type, which is always `score_model`.""" range: Optional[List[float]] = None """The range of the score. Defaults to `[0, 1]`.""" sampling_params: Optional[SamplingParams] = None """The sampling parameters for the model.""" ================================================ FILE: src/openai/types/graders/score_model_grader_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from .grader_inputs_param import GraderInputsParam from ..shared.reasoning_effort import ReasoningEffort from ..responses.response_input_text_param import ResponseInputTextParam from ..responses.response_input_audio_param import ResponseInputAudioParam __all__ = [ "ScoreModelGraderParam", "Input", "InputContent", "InputContentOutputText", "InputContentInputImage", "SamplingParams", ] class InputContentOutputText(TypedDict, total=False): """A text output from the model.""" text: Required[str] """The text output from the model.""" type: Required[Literal["output_text"]] """The type of the output text. Always `output_text`.""" class InputContentInputImage(TypedDict, total=False): """An image input block used within EvalItem content arrays.""" image_url: Required[str] """The URL of the image input.""" type: Required[Literal["input_image"]] """The type of the image input. Always `input_image`.""" detail: str """The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. Defaults to `auto`. """ InputContent: TypeAlias = Union[ str, ResponseInputTextParam, InputContentOutputText, InputContentInputImage, ResponseInputAudioParam, GraderInputsParam, ] class Input(TypedDict, total=False): """ A message input to the model with a role indicating instruction following hierarchy. Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role. Messages with the `assistant` role are presumed to have been generated by the model in previous interactions. """ content: Required[InputContent] """Inputs to the model - can contain template strings. Supports text, output text, input images, and input audio, either as a single item or an array of items. """ role: Required[Literal["user", "assistant", "system", "developer"]] """The role of the message input. One of `user`, `assistant`, `system`, or `developer`. """ type: Literal["message"] """The type of the message input. Always `message`.""" class SamplingParams(TypedDict, total=False): """The sampling parameters for the model.""" max_completions_tokens: Optional[int] """The maximum number of tokens the grader model may generate in its response.""" reasoning_effort: Optional[ReasoningEffort] """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ seed: Optional[int] """A seed value to initialize the randomness, during sampling.""" temperature: Optional[float] """A higher temperature increases randomness in the outputs.""" top_p: Optional[float] """An alternative to temperature for nucleus sampling; 1.0 includes all tokens.""" class ScoreModelGraderParam(TypedDict, total=False): """A ScoreModelGrader object that uses a model to assign a score to the input.""" input: Required[Iterable[Input]] """The input messages evaluated by the grader. Supports text, output text, input image, and input audio content blocks, and may include template strings. """ model: Required[str] """The model to use for the evaluation.""" name: Required[str] """The name of the grader.""" type: Required[Literal["score_model"]] """The object type, which is always `score_model`.""" range: Iterable[float] """The range of the score. Defaults to `[0, 1]`.""" sampling_params: SamplingParams """The sampling parameters for the model.""" ================================================ FILE: src/openai/types/graders/string_check_grader.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["StringCheckGrader"] class StringCheckGrader(BaseModel): """ A StringCheckGrader object that performs a string comparison between input and reference using a specified operation. """ input: str """The input text. This may include template strings.""" name: str """The name of the grader.""" operation: Literal["eq", "ne", "like", "ilike"] """The string check operation to perform. One of `eq`, `ne`, `like`, or `ilike`.""" reference: str """The reference text. This may include template strings.""" type: Literal["string_check"] """The object type, which is always `string_check`.""" ================================================ FILE: src/openai/types/graders/string_check_grader_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["StringCheckGraderParam"] class StringCheckGraderParam(TypedDict, total=False): """ A StringCheckGrader object that performs a string comparison between input and reference using a specified operation. """ input: Required[str] """The input text. This may include template strings.""" name: Required[str] """The name of the grader.""" operation: Required[Literal["eq", "ne", "like", "ilike"]] """The string check operation to perform. One of `eq`, `ne`, `like`, or `ilike`.""" reference: Required[str] """The reference text. This may include template strings.""" type: Required[Literal["string_check"]] """The object type, which is always `string_check`.""" ================================================ FILE: src/openai/types/graders/text_similarity_grader.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["TextSimilarityGrader"] class TextSimilarityGrader(BaseModel): """A TextSimilarityGrader object which grades text based on similarity metrics.""" evaluation_metric: Literal[ "cosine", "fuzzy_match", "bleu", "gleu", "meteor", "rouge_1", "rouge_2", "rouge_3", "rouge_4", "rouge_5", "rouge_l", ] """The evaluation metric to use. One of `cosine`, `fuzzy_match`, `bleu`, `gleu`, `meteor`, `rouge_1`, `rouge_2`, `rouge_3`, `rouge_4`, `rouge_5`, or `rouge_l`. """ input: str """The text being graded.""" name: str """The name of the grader.""" reference: str """The text being graded against.""" type: Literal["text_similarity"] """The type of grader.""" ================================================ FILE: src/openai/types/graders/text_similarity_grader_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["TextSimilarityGraderParam"] class TextSimilarityGraderParam(TypedDict, total=False): """A TextSimilarityGrader object which grades text based on similarity metrics.""" evaluation_metric: Required[ Literal[ "cosine", "fuzzy_match", "bleu", "gleu", "meteor", "rouge_1", "rouge_2", "rouge_3", "rouge_4", "rouge_5", "rouge_l", ] ] """The evaluation metric to use. One of `cosine`, `fuzzy_match`, `bleu`, `gleu`, `meteor`, `rouge_1`, `rouge_2`, `rouge_3`, `rouge_4`, `rouge_5`, or `rouge_l`. """ input: Required[str] """The text being graded.""" name: Required[str] """The name of the grader.""" reference: Required[str] """The text being graded against.""" type: Required[Literal["text_similarity"]] """The type of grader.""" ================================================ FILE: src/openai/types/image.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from .._models import BaseModel __all__ = ["Image"] class Image(BaseModel): """Represents the content or the URL of an image generated by the OpenAI API.""" b64_json: Optional[str] = None """The base64-encoded JSON of the generated image. Returned by default for the GPT image models, and only present if `response_format` is set to `b64_json` for `dall-e-2` and `dall-e-3`. """ revised_prompt: Optional[str] = None """For `dall-e-3` only, the revised prompt that was used to generate the image.""" url: Optional[str] = None """ When using `dall-e-2` or `dall-e-3`, the URL of the generated image if `response_format` is set to `url` (default value). Unsupported for the GPT image models. """ ================================================ FILE: src/openai/types/image_create_variation_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Optional from typing_extensions import Literal, Required, TypedDict from .._types import FileTypes from .image_model import ImageModel __all__ = ["ImageCreateVariationParams"] class ImageCreateVariationParams(TypedDict, total=False): image: Required[FileTypes] """The image to use as the basis for the variation(s). Must be a valid PNG file, less than 4MB, and square. """ model: Union[str, ImageModel, None] """The model to use for image generation. Only `dall-e-2` is supported at this time. """ n: Optional[int] """The number of images to generate. Must be between 1 and 10.""" response_format: Optional[Literal["url", "b64_json"]] """The format in which the generated images are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. """ size: Optional[Literal["256x256", "512x512", "1024x1024"]] """The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. """ user: str """ A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). """ ================================================ FILE: src/openai/types/image_edit_completed_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .._models import BaseModel __all__ = ["ImageEditCompletedEvent", "Usage", "UsageInputTokensDetails"] class UsageInputTokensDetails(BaseModel): """The input tokens detailed information for the image generation.""" image_tokens: int """The number of image tokens in the input prompt.""" text_tokens: int """The number of text tokens in the input prompt.""" class Usage(BaseModel): """ For the GPT image models only, the token usage information for the image generation. """ input_tokens: int """The number of tokens (images and text) in the input prompt.""" input_tokens_details: UsageInputTokensDetails """The input tokens detailed information for the image generation.""" output_tokens: int """The number of image tokens in the output image.""" total_tokens: int """The total number of tokens (images and text) used for the image generation.""" class ImageEditCompletedEvent(BaseModel): """Emitted when image editing has completed and the final image is available.""" b64_json: str """Base64-encoded final edited image data, suitable for rendering as an image.""" background: Literal["transparent", "opaque", "auto"] """The background setting for the edited image.""" created_at: int """The Unix timestamp when the event was created.""" output_format: Literal["png", "webp", "jpeg"] """The output format for the edited image.""" quality: Literal["low", "medium", "high", "auto"] """The quality setting for the edited image.""" size: Literal["1024x1024", "1024x1536", "1536x1024", "auto"] """The size of the edited image.""" type: Literal["image_edit.completed"] """The type of the event. Always `image_edit.completed`.""" usage: Usage """ For the GPT image models only, the token usage information for the image generation. """ ================================================ FILE: src/openai/types/image_edit_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Optional from typing_extensions import Literal, Required, TypedDict from .._types import FileTypes, SequenceNotStr from .image_model import ImageModel __all__ = ["ImageEditParamsBase", "ImageEditParamsNonStreaming", "ImageEditParamsStreaming"] class ImageEditParamsBase(TypedDict, total=False): image: Required[Union[FileTypes, SequenceNotStr[FileTypes]]] """The image(s) to edit. Must be a supported image file or an array of images. For the GPT image models (`gpt-image-1`, `gpt-image-1-mini`, and `gpt-image-1.5`), each image should be a `png`, `webp`, or `jpg` file less than 50MB. You can provide up to 16 images. `chatgpt-image-latest` follows the same input constraints as GPT image models. For `dall-e-2`, you can only provide one image, and it should be a square `png` file less than 4MB. """ prompt: Required[str] """A text description of the desired image(s). The maximum length is 1000 characters for `dall-e-2`, and 32000 characters for the GPT image models. """ background: Optional[Literal["transparent", "opaque", "auto"]] """ Allows to set transparency for the background of the generated image(s). This parameter is only supported for the GPT image models. Must be one of `transparent`, `opaque` or `auto` (default value). When `auto` is used, the model will automatically determine the best background for the image. If `transparent`, the output format needs to support transparency, so it should be set to either `png` (default value) or `webp`. """ input_fidelity: Optional[Literal["high", "low"]] """ Control how much effort the model will exert to match the style and features, especially facial features, of input images. This parameter is only supported for `gpt-image-1` and `gpt-image-1.5` and later models, unsupported for `gpt-image-1-mini`. Supports `high` and `low`. Defaults to `low`. """ mask: FileTypes """An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where `image` should be edited. If there are multiple images provided, the mask will be applied on the first image. Must be a valid PNG file, less than 4MB, and have the same dimensions as `image`. """ model: Union[str, ImageModel, None] """The model to use for image generation. Defaults to `gpt-image-1.5`.""" n: Optional[int] """The number of images to generate. Must be between 1 and 10.""" output_compression: Optional[int] """The compression level (0-100%) for the generated images. This parameter is only supported for the GPT image models with the `webp` or `jpeg` output formats, and defaults to 100. """ output_format: Optional[Literal["png", "jpeg", "webp"]] """The format in which the generated images are returned. This parameter is only supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`. The default value is `png`. """ partial_images: Optional[int] """The number of partial images to generate. This parameter is used for streaming responses that return partial images. Value must be between 0 and 3. When set to 0, the response will be a single image sent in one streaming event. Note that the final image may be sent before the full number of partial images are generated if the full image is generated more quickly. """ quality: Optional[Literal["standard", "low", "medium", "high", "auto"]] """The quality of the image that will be generated for GPT image models. Defaults to `auto`. """ response_format: Optional[Literal["url", "b64_json"]] """The format in which the generated images are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. This parameter is only supported for `dall-e-2` (default is `url` for `dall-e-2`), as GPT image models always return base64-encoded images. """ size: Optional[Literal["256x256", "512x512", "1024x1024", "1536x1024", "1024x1536", "auto"]] """The size of the generated images. Must be one of `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto` (default value) for the GPT image models, and one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`. """ user: str """ A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). """ class ImageEditParamsNonStreaming(ImageEditParamsBase, total=False): stream: Optional[Literal[False]] """Edit the image in streaming mode. Defaults to `false`. See the [Image generation guide](https://platform.openai.com/docs/guides/image-generation) for more information. """ class ImageEditParamsStreaming(ImageEditParamsBase): stream: Required[Literal[True]] """Edit the image in streaming mode. Defaults to `false`. See the [Image generation guide](https://platform.openai.com/docs/guides/image-generation) for more information. """ ImageEditParams = Union[ImageEditParamsNonStreaming, ImageEditParamsStreaming] ================================================ FILE: src/openai/types/image_edit_partial_image_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .._models import BaseModel __all__ = ["ImageEditPartialImageEvent"] class ImageEditPartialImageEvent(BaseModel): """Emitted when a partial image is available during image editing streaming.""" b64_json: str """Base64-encoded partial image data, suitable for rendering as an image.""" background: Literal["transparent", "opaque", "auto"] """The background setting for the requested edited image.""" created_at: int """The Unix timestamp when the event was created.""" output_format: Literal["png", "webp", "jpeg"] """The output format for the requested edited image.""" partial_image_index: int """0-based index for the partial image (streaming).""" quality: Literal["low", "medium", "high", "auto"] """The quality setting for the requested edited image.""" size: Literal["1024x1024", "1024x1536", "1536x1024", "auto"] """The size of the requested edited image.""" type: Literal["image_edit.partial_image"] """The type of the event. Always `image_edit.partial_image`.""" ================================================ FILE: src/openai/types/image_edit_stream_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from .._utils import PropertyInfo from .image_edit_completed_event import ImageEditCompletedEvent from .image_edit_partial_image_event import ImageEditPartialImageEvent __all__ = ["ImageEditStreamEvent"] ImageEditStreamEvent: TypeAlias = Annotated[ Union[ImageEditPartialImageEvent, ImageEditCompletedEvent], PropertyInfo(discriminator="type") ] ================================================ FILE: src/openai/types/image_gen_completed_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .._models import BaseModel __all__ = ["ImageGenCompletedEvent", "Usage", "UsageInputTokensDetails"] class UsageInputTokensDetails(BaseModel): """The input tokens detailed information for the image generation.""" image_tokens: int """The number of image tokens in the input prompt.""" text_tokens: int """The number of text tokens in the input prompt.""" class Usage(BaseModel): """ For the GPT image models only, the token usage information for the image generation. """ input_tokens: int """The number of tokens (images and text) in the input prompt.""" input_tokens_details: UsageInputTokensDetails """The input tokens detailed information for the image generation.""" output_tokens: int """The number of image tokens in the output image.""" total_tokens: int """The total number of tokens (images and text) used for the image generation.""" class ImageGenCompletedEvent(BaseModel): """Emitted when image generation has completed and the final image is available.""" b64_json: str """Base64-encoded image data, suitable for rendering as an image.""" background: Literal["transparent", "opaque", "auto"] """The background setting for the generated image.""" created_at: int """The Unix timestamp when the event was created.""" output_format: Literal["png", "webp", "jpeg"] """The output format for the generated image.""" quality: Literal["low", "medium", "high", "auto"] """The quality setting for the generated image.""" size: Literal["1024x1024", "1024x1536", "1536x1024", "auto"] """The size of the generated image.""" type: Literal["image_generation.completed"] """The type of the event. Always `image_generation.completed`.""" usage: Usage """ For the GPT image models only, the token usage information for the image generation. """ ================================================ FILE: src/openai/types/image_gen_partial_image_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .._models import BaseModel __all__ = ["ImageGenPartialImageEvent"] class ImageGenPartialImageEvent(BaseModel): """Emitted when a partial image is available during image generation streaming.""" b64_json: str """Base64-encoded partial image data, suitable for rendering as an image.""" background: Literal["transparent", "opaque", "auto"] """The background setting for the requested image.""" created_at: int """The Unix timestamp when the event was created.""" output_format: Literal["png", "webp", "jpeg"] """The output format for the requested image.""" partial_image_index: int """0-based index for the partial image (streaming).""" quality: Literal["low", "medium", "high", "auto"] """The quality setting for the requested image.""" size: Literal["1024x1024", "1024x1536", "1536x1024", "auto"] """The size of the requested image.""" type: Literal["image_generation.partial_image"] """The type of the event. Always `image_generation.partial_image`.""" ================================================ FILE: src/openai/types/image_gen_stream_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from .._utils import PropertyInfo from .image_gen_completed_event import ImageGenCompletedEvent from .image_gen_partial_image_event import ImageGenPartialImageEvent __all__ = ["ImageGenStreamEvent"] ImageGenStreamEvent: TypeAlias = Annotated[ Union[ImageGenPartialImageEvent, ImageGenCompletedEvent], PropertyInfo(discriminator="type") ] ================================================ FILE: src/openai/types/image_generate_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Optional from typing_extensions import Literal, Required, TypedDict from .image_model import ImageModel __all__ = ["ImageGenerateParamsBase", "ImageGenerateParamsNonStreaming", "ImageGenerateParamsStreaming"] class ImageGenerateParamsBase(TypedDict, total=False): prompt: Required[str] """A text description of the desired image(s). The maximum length is 32000 characters for the GPT image models, 1000 characters for `dall-e-2` and 4000 characters for `dall-e-3`. """ background: Optional[Literal["transparent", "opaque", "auto"]] """ Allows to set transparency for the background of the generated image(s). This parameter is only supported for the GPT image models. Must be one of `transparent`, `opaque` or `auto` (default value). When `auto` is used, the model will automatically determine the best background for the image. If `transparent`, the output format needs to support transparency, so it should be set to either `png` (default value) or `webp`. """ model: Union[str, ImageModel, None] """The model to use for image generation. One of `dall-e-2`, `dall-e-3`, or a GPT image model (`gpt-image-1`, `gpt-image-1-mini`, `gpt-image-1.5`). Defaults to `dall-e-2` unless a parameter specific to the GPT image models is used. """ moderation: Optional[Literal["low", "auto"]] """ Control the content-moderation level for images generated by the GPT image models. Must be either `low` for less restrictive filtering or `auto` (default value). """ n: Optional[int] """The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is supported. """ output_compression: Optional[int] """The compression level (0-100%) for the generated images. This parameter is only supported for the GPT image models with the `webp` or `jpeg` output formats, and defaults to 100. """ output_format: Optional[Literal["png", "jpeg", "webp"]] """The format in which the generated images are returned. This parameter is only supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`. """ partial_images: Optional[int] """The number of partial images to generate. This parameter is used for streaming responses that return partial images. Value must be between 0 and 3. When set to 0, the response will be a single image sent in one streaming event. Note that the final image may be sent before the full number of partial images are generated if the full image is generated more quickly. """ quality: Optional[Literal["standard", "hd", "low", "medium", "high", "auto"]] """The quality of the image that will be generated. - `auto` (default value) will automatically select the best quality for the given model. - `high`, `medium` and `low` are supported for the GPT image models. - `hd` and `standard` are supported for `dall-e-3`. - `standard` is the only option for `dall-e-2`. """ response_format: Optional[Literal["url", "b64_json"]] """The format in which generated images with `dall-e-2` and `dall-e-3` are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. This parameter isn't supported for the GPT image models, which always return base64-encoded images. """ size: Optional[ Literal["auto", "1024x1024", "1536x1024", "1024x1536", "256x256", "512x512", "1792x1024", "1024x1792"] ] """The size of the generated images. Must be one of `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto` (default value) for the GPT image models, one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`, and one of `1024x1024`, `1792x1024`, or `1024x1792` for `dall-e-3`. """ style: Optional[Literal["vivid", "natural"]] """The style of the generated images. This parameter is only supported for `dall-e-3`. Must be one of `vivid` or `natural`. Vivid causes the model to lean towards generating hyper-real and dramatic images. Natural causes the model to produce more natural, less hyper-real looking images. """ user: str """ A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). """ class ImageGenerateParamsNonStreaming(ImageGenerateParamsBase, total=False): stream: Optional[Literal[False]] """Generate the image in streaming mode. Defaults to `false`. See the [Image generation guide](https://platform.openai.com/docs/guides/image-generation) for more information. This parameter is only supported for the GPT image models. """ class ImageGenerateParamsStreaming(ImageGenerateParamsBase): stream: Required[Literal[True]] """Generate the image in streaming mode. Defaults to `false`. See the [Image generation guide](https://platform.openai.com/docs/guides/image-generation) for more information. This parameter is only supported for the GPT image models. """ ImageGenerateParams = Union[ImageGenerateParamsNonStreaming, ImageGenerateParamsStreaming] ================================================ FILE: src/openai/types/image_input_reference_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import TypedDict __all__ = ["ImageInputReferenceParam"] class ImageInputReferenceParam(TypedDict, total=False): file_id: str image_url: str """A fully qualified URL or base64-encoded data URL.""" ================================================ FILE: src/openai/types/image_model.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["ImageModel"] ImageModel: TypeAlias = Literal["gpt-image-1.5", "dall-e-2", "dall-e-3", "gpt-image-1", "gpt-image-1-mini"] ================================================ FILE: src/openai/types/images_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from .image import Image from .._models import BaseModel __all__ = ["ImagesResponse", "Usage", "UsageInputTokensDetails", "UsageOutputTokensDetails"] class UsageInputTokensDetails(BaseModel): """The input tokens detailed information for the image generation.""" image_tokens: int """The number of image tokens in the input prompt.""" text_tokens: int """The number of text tokens in the input prompt.""" class UsageOutputTokensDetails(BaseModel): """The output token details for the image generation.""" image_tokens: int """The number of image output tokens generated by the model.""" text_tokens: int """The number of text output tokens generated by the model.""" class Usage(BaseModel): """For `gpt-image-1` only, the token usage information for the image generation.""" input_tokens: int """The number of tokens (images and text) in the input prompt.""" input_tokens_details: UsageInputTokensDetails """The input tokens detailed information for the image generation.""" output_tokens: int """The number of output tokens generated by the model.""" total_tokens: int """The total number of tokens (images and text) used for the image generation.""" output_tokens_details: Optional[UsageOutputTokensDetails] = None """The output token details for the image generation.""" class ImagesResponse(BaseModel): """The response from the image generation endpoint.""" created: int """The Unix timestamp (in seconds) of when the image was created.""" background: Optional[Literal["transparent", "opaque"]] = None """The background parameter used for the image generation. Either `transparent` or `opaque`. """ data: Optional[List[Image]] = None """The list of generated images.""" output_format: Optional[Literal["png", "webp", "jpeg"]] = None """The output format of the image generation. Either `png`, `webp`, or `jpeg`.""" quality: Optional[Literal["low", "medium", "high"]] = None """The quality of the image generated. Either `low`, `medium`, or `high`.""" size: Optional[Literal["1024x1024", "1024x1536", "1536x1024"]] = None """The size of the image generated. Either `1024x1024`, `1024x1536`, or `1536x1024`. """ usage: Optional[Usage] = None """For `gpt-image-1` only, the token usage information for the image generation.""" ================================================ FILE: src/openai/types/model.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .._models import BaseModel __all__ = ["Model"] class Model(BaseModel): """Describes an OpenAI model offering that can be used with the API.""" id: str """The model identifier, which can be referenced in the API endpoints.""" created: int """The Unix timestamp (in seconds) when the model was created.""" object: Literal["model"] """The object type, which is always "model".""" owned_by: str """The organization that owns the model.""" ================================================ FILE: src/openai/types/model_deleted.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .._models import BaseModel __all__ = ["ModelDeleted"] class ModelDeleted(BaseModel): id: str deleted: bool object: str ================================================ FILE: src/openai/types/moderation.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from pydantic import Field as FieldInfo from .._models import BaseModel __all__ = ["Moderation", "Categories", "CategoryAppliedInputTypes", "CategoryScores"] class Categories(BaseModel): """A list of the categories, and whether they are flagged or not.""" harassment: bool """ Content that expresses, incites, or promotes harassing language towards any target. """ harassment_threatening: bool = FieldInfo(alias="harassment/threatening") """ Harassment content that also includes violence or serious harm towards any target. """ hate: bool """ Content that expresses, incites, or promotes hate based on race, gender, ethnicity, religion, nationality, sexual orientation, disability status, or caste. Hateful content aimed at non-protected groups (e.g., chess players) is harassment. """ hate_threatening: bool = FieldInfo(alias="hate/threatening") """ Hateful content that also includes violence or serious harm towards the targeted group based on race, gender, ethnicity, religion, nationality, sexual orientation, disability status, or caste. """ illicit: Optional[bool] = None """ Content that includes instructions or advice that facilitate the planning or execution of wrongdoing, or that gives advice or instruction on how to commit illicit acts. For example, "how to shoplift" would fit this category. """ illicit_violent: Optional[bool] = FieldInfo(alias="illicit/violent", default=None) """ Content that includes instructions or advice that facilitate the planning or execution of wrongdoing that also includes violence, or that gives advice or instruction on the procurement of any weapon. """ self_harm: bool = FieldInfo(alias="self-harm") """ Content that promotes, encourages, or depicts acts of self-harm, such as suicide, cutting, and eating disorders. """ self_harm_instructions: bool = FieldInfo(alias="self-harm/instructions") """ Content that encourages performing acts of self-harm, such as suicide, cutting, and eating disorders, or that gives instructions or advice on how to commit such acts. """ self_harm_intent: bool = FieldInfo(alias="self-harm/intent") """ Content where the speaker expresses that they are engaging or intend to engage in acts of self-harm, such as suicide, cutting, and eating disorders. """ sexual: bool """ Content meant to arouse sexual excitement, such as the description of sexual activity, or that promotes sexual services (excluding sex education and wellness). """ sexual_minors: bool = FieldInfo(alias="sexual/minors") """Sexual content that includes an individual who is under 18 years old.""" violence: bool """Content that depicts death, violence, or physical injury.""" violence_graphic: bool = FieldInfo(alias="violence/graphic") """Content that depicts death, violence, or physical injury in graphic detail.""" class CategoryAppliedInputTypes(BaseModel): """ A list of the categories along with the input type(s) that the score applies to. """ harassment: List[Literal["text"]] """The applied input type(s) for the category 'harassment'.""" harassment_threatening: List[Literal["text"]] = FieldInfo(alias="harassment/threatening") """The applied input type(s) for the category 'harassment/threatening'.""" hate: List[Literal["text"]] """The applied input type(s) for the category 'hate'.""" hate_threatening: List[Literal["text"]] = FieldInfo(alias="hate/threatening") """The applied input type(s) for the category 'hate/threatening'.""" illicit: List[Literal["text"]] """The applied input type(s) for the category 'illicit'.""" illicit_violent: List[Literal["text"]] = FieldInfo(alias="illicit/violent") """The applied input type(s) for the category 'illicit/violent'.""" self_harm: List[Literal["text", "image"]] = FieldInfo(alias="self-harm") """The applied input type(s) for the category 'self-harm'.""" self_harm_instructions: List[Literal["text", "image"]] = FieldInfo(alias="self-harm/instructions") """The applied input type(s) for the category 'self-harm/instructions'.""" self_harm_intent: List[Literal["text", "image"]] = FieldInfo(alias="self-harm/intent") """The applied input type(s) for the category 'self-harm/intent'.""" sexual: List[Literal["text", "image"]] """The applied input type(s) for the category 'sexual'.""" sexual_minors: List[Literal["text"]] = FieldInfo(alias="sexual/minors") """The applied input type(s) for the category 'sexual/minors'.""" violence: List[Literal["text", "image"]] """The applied input type(s) for the category 'violence'.""" violence_graphic: List[Literal["text", "image"]] = FieldInfo(alias="violence/graphic") """The applied input type(s) for the category 'violence/graphic'.""" class CategoryScores(BaseModel): """A list of the categories along with their scores as predicted by model.""" harassment: float """The score for the category 'harassment'.""" harassment_threatening: float = FieldInfo(alias="harassment/threatening") """The score for the category 'harassment/threatening'.""" hate: float """The score for the category 'hate'.""" hate_threatening: float = FieldInfo(alias="hate/threatening") """The score for the category 'hate/threatening'.""" illicit: float """The score for the category 'illicit'.""" illicit_violent: float = FieldInfo(alias="illicit/violent") """The score for the category 'illicit/violent'.""" self_harm: float = FieldInfo(alias="self-harm") """The score for the category 'self-harm'.""" self_harm_instructions: float = FieldInfo(alias="self-harm/instructions") """The score for the category 'self-harm/instructions'.""" self_harm_intent: float = FieldInfo(alias="self-harm/intent") """The score for the category 'self-harm/intent'.""" sexual: float """The score for the category 'sexual'.""" sexual_minors: float = FieldInfo(alias="sexual/minors") """The score for the category 'sexual/minors'.""" violence: float """The score for the category 'violence'.""" violence_graphic: float = FieldInfo(alias="violence/graphic") """The score for the category 'violence/graphic'.""" class Moderation(BaseModel): categories: Categories """A list of the categories, and whether they are flagged or not.""" category_applied_input_types: CategoryAppliedInputTypes """ A list of the categories along with the input type(s) that the score applies to. """ category_scores: CategoryScores """A list of the categories along with their scores as predicted by model.""" flagged: bool """Whether any of the below categories are flagged.""" ================================================ FILE: src/openai/types/moderation_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable from typing_extensions import Required, TypedDict from .._types import SequenceNotStr from .moderation_model import ModerationModel from .moderation_multi_modal_input_param import ModerationMultiModalInputParam __all__ = ["ModerationCreateParams"] class ModerationCreateParams(TypedDict, total=False): input: Required[Union[str, SequenceNotStr[str], Iterable[ModerationMultiModalInputParam]]] """Input (or inputs) to classify. Can be a single string, an array of strings, or an array of multi-modal input objects similar to other models. """ model: Union[str, ModerationModel] """The content moderation model you would like to use. Learn more in [the moderation guide](https://platform.openai.com/docs/guides/moderation), and learn about available models [here](https://platform.openai.com/docs/models#moderation). """ ================================================ FILE: src/openai/types/moderation_create_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List from .._models import BaseModel from .moderation import Moderation __all__ = ["ModerationCreateResponse"] class ModerationCreateResponse(BaseModel): """Represents if a given text input is potentially harmful.""" id: str """The unique identifier for the moderation request.""" model: str """The model used to generate the moderation results.""" results: List[Moderation] """A list of moderation objects.""" ================================================ FILE: src/openai/types/moderation_image_url_input_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ModerationImageURLInputParam", "ImageURL"] class ImageURL(TypedDict, total=False): """Contains either an image URL or a data URL for a base64 encoded image.""" url: Required[str] """Either a URL of the image or the base64 encoded image data.""" class ModerationImageURLInputParam(TypedDict, total=False): """An object describing an image to classify.""" image_url: Required[ImageURL] """Contains either an image URL or a data URL for a base64 encoded image.""" type: Required[Literal["image_url"]] """Always `image_url`.""" ================================================ FILE: src/openai/types/moderation_model.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["ModerationModel"] ModerationModel: TypeAlias = Literal[ "omni-moderation-latest", "omni-moderation-2024-09-26", "text-moderation-latest", "text-moderation-stable" ] ================================================ FILE: src/openai/types/moderation_multi_modal_input_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import TypeAlias from .moderation_text_input_param import ModerationTextInputParam from .moderation_image_url_input_param import ModerationImageURLInputParam __all__ = ["ModerationMultiModalInputParam"] ModerationMultiModalInputParam: TypeAlias = Union[ModerationImageURLInputParam, ModerationTextInputParam] ================================================ FILE: src/openai/types/moderation_text_input_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ModerationTextInputParam"] class ModerationTextInputParam(TypedDict, total=False): """An object describing text to classify.""" text: Required[str] """A string of text to classify.""" type: Required[Literal["text"]] """Always `text`.""" ================================================ FILE: src/openai/types/other_file_chunking_strategy_object.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .._models import BaseModel __all__ = ["OtherFileChunkingStrategyObject"] class OtherFileChunkingStrategyObject(BaseModel): """This is returned when the chunking strategy is unknown. Typically, this is because the file was indexed before the `chunking_strategy` concept was introduced in the API. """ type: Literal["other"] """Always `other`.""" ================================================ FILE: src/openai/types/realtime/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .realtime_error import RealtimeError as RealtimeError from .call_refer_params import CallReferParams as CallReferParams from .conversation_item import ConversationItem as ConversationItem from .realtime_response import RealtimeResponse as RealtimeResponse from .call_accept_params import CallAcceptParams as CallAcceptParams from .call_create_params import CallCreateParams as CallCreateParams from .call_reject_params import CallRejectParams as CallRejectParams from .audio_transcription import AudioTranscription as AudioTranscription from .log_prob_properties import LogProbProperties as LogProbProperties from .realtime_truncation import RealtimeTruncation as RealtimeTruncation from .response_done_event import ResponseDoneEvent as ResponseDoneEvent from .noise_reduction_type import NoiseReductionType as NoiseReductionType from .realtime_error_event import RealtimeErrorEvent as RealtimeErrorEvent from .session_update_event import SessionUpdateEvent as SessionUpdateEvent from .mcp_list_tools_failed import McpListToolsFailed as McpListToolsFailed from .realtime_audio_config import RealtimeAudioConfig as RealtimeAudioConfig from .realtime_client_event import RealtimeClientEvent as RealtimeClientEvent from .realtime_server_event import RealtimeServerEvent as RealtimeServerEvent from .realtime_tools_config import RealtimeToolsConfig as RealtimeToolsConfig from .response_cancel_event import ResponseCancelEvent as ResponseCancelEvent from .response_create_event import ResponseCreateEvent as ResponseCreateEvent from .session_created_event import SessionCreatedEvent as SessionCreatedEvent from .session_updated_event import SessionUpdatedEvent as SessionUpdatedEvent from .conversation_item_done import ConversationItemDone as ConversationItemDone from .realtime_audio_formats import RealtimeAudioFormats as RealtimeAudioFormats from .realtime_function_tool import RealtimeFunctionTool as RealtimeFunctionTool from .realtime_mcp_tool_call import RealtimeMcpToolCall as RealtimeMcpToolCall from .realtime_mcphttp_error import RealtimeMcphttpError as RealtimeMcphttpError from .response_created_event import ResponseCreatedEvent as ResponseCreatedEvent from .conversation_item_added import ConversationItemAdded as ConversationItemAdded from .conversation_item_param import ConversationItemParam as ConversationItemParam from .realtime_connect_params import RealtimeConnectParams as RealtimeConnectParams from .realtime_mcp_list_tools import RealtimeMcpListTools as RealtimeMcpListTools from .realtime_response_usage import RealtimeResponseUsage as RealtimeResponseUsage from .realtime_tracing_config import RealtimeTracingConfig as RealtimeTracingConfig from .mcp_list_tools_completed import McpListToolsCompleted as McpListToolsCompleted from .realtime_response_status import RealtimeResponseStatus as RealtimeResponseStatus from .response_mcp_call_failed import ResponseMcpCallFailed as ResponseMcpCallFailed from .response_text_done_event import ResponseTextDoneEvent as ResponseTextDoneEvent from .audio_transcription_param import AudioTranscriptionParam as AudioTranscriptionParam from .rate_limits_updated_event import RateLimitsUpdatedEvent as RateLimitsUpdatedEvent from .realtime_truncation_param import RealtimeTruncationParam as RealtimeTruncationParam from .response_audio_done_event import ResponseAudioDoneEvent as ResponseAudioDoneEvent from .response_text_delta_event import ResponseTextDeltaEvent as ResponseTextDeltaEvent from .conversation_created_event import ConversationCreatedEvent as ConversationCreatedEvent from .mcp_list_tools_in_progress import McpListToolsInProgress as McpListToolsInProgress from .response_audio_delta_event import ResponseAudioDeltaEvent as ResponseAudioDeltaEvent from .session_update_event_param import SessionUpdateEventParam as SessionUpdateEventParam from .client_secret_create_params import ClientSecretCreateParams as ClientSecretCreateParams from .realtime_audio_config_input import RealtimeAudioConfigInput as RealtimeAudioConfigInput from .realtime_audio_config_param import RealtimeAudioConfigParam as RealtimeAudioConfigParam from .realtime_client_event_param import RealtimeClientEventParam as RealtimeClientEventParam from .realtime_mcp_protocol_error import RealtimeMcpProtocolError as RealtimeMcpProtocolError from .realtime_tool_choice_config import RealtimeToolChoiceConfig as RealtimeToolChoiceConfig from .realtime_tools_config_param import RealtimeToolsConfigParam as RealtimeToolsConfigParam from .realtime_tools_config_union import RealtimeToolsConfigUnion as RealtimeToolsConfigUnion from .response_cancel_event_param import ResponseCancelEventParam as ResponseCancelEventParam from .response_create_event_param import ResponseCreateEventParam as ResponseCreateEventParam from .response_mcp_call_completed import ResponseMcpCallCompleted as ResponseMcpCallCompleted from .realtime_audio_config_output import RealtimeAudioConfigOutput as RealtimeAudioConfigOutput from .realtime_audio_formats_param import RealtimeAudioFormatsParam as RealtimeAudioFormatsParam from .realtime_function_tool_param import RealtimeFunctionToolParam as RealtimeFunctionToolParam from .realtime_mcp_tool_call_param import RealtimeMcpToolCallParam as RealtimeMcpToolCallParam from .realtime_mcphttp_error_param import RealtimeMcphttpErrorParam as RealtimeMcphttpErrorParam from .client_secret_create_response import ClientSecretCreateResponse as ClientSecretCreateResponse from .realtime_mcp_approval_request import RealtimeMcpApprovalRequest as RealtimeMcpApprovalRequest from .realtime_mcp_list_tools_param import RealtimeMcpListToolsParam as RealtimeMcpListToolsParam from .realtime_tracing_config_param import RealtimeTracingConfigParam as RealtimeTracingConfigParam from .response_mcp_call_in_progress import ResponseMcpCallInProgress as ResponseMcpCallInProgress from .conversation_item_create_event import ConversationItemCreateEvent as ConversationItemCreateEvent from .conversation_item_delete_event import ConversationItemDeleteEvent as ConversationItemDeleteEvent from .input_audio_buffer_clear_event import InputAudioBufferClearEvent as InputAudioBufferClearEvent from .realtime_mcp_approval_response import RealtimeMcpApprovalResponse as RealtimeMcpApprovalResponse from .realtime_session_client_secret import RealtimeSessionClientSecret as RealtimeSessionClientSecret from .conversation_item_created_event import ConversationItemCreatedEvent as ConversationItemCreatedEvent from .conversation_item_deleted_event import ConversationItemDeletedEvent as ConversationItemDeletedEvent from .input_audio_buffer_append_event import InputAudioBufferAppendEvent as InputAudioBufferAppendEvent from .input_audio_buffer_commit_event import InputAudioBufferCommitEvent as InputAudioBufferCommitEvent from .output_audio_buffer_clear_event import OutputAudioBufferClearEvent as OutputAudioBufferClearEvent from .realtime_response_create_params import RealtimeResponseCreateParams as RealtimeResponseCreateParams from .realtime_session_create_request import RealtimeSessionCreateRequest as RealtimeSessionCreateRequest from .response_output_item_done_event import ResponseOutputItemDoneEvent as ResponseOutputItemDoneEvent from .conversation_item_retrieve_event import ConversationItemRetrieveEvent as ConversationItemRetrieveEvent from .conversation_item_truncate_event import ConversationItemTruncateEvent as ConversationItemTruncateEvent from .input_audio_buffer_cleared_event import InputAudioBufferClearedEvent as InputAudioBufferClearedEvent from .realtime_session_create_response import RealtimeSessionCreateResponse as RealtimeSessionCreateResponse from .response_content_part_done_event import ResponseContentPartDoneEvent as ResponseContentPartDoneEvent from .response_mcp_call_arguments_done import ResponseMcpCallArgumentsDone as ResponseMcpCallArgumentsDone from .response_output_item_added_event import ResponseOutputItemAddedEvent as ResponseOutputItemAddedEvent from .conversation_item_truncated_event import ConversationItemTruncatedEvent as ConversationItemTruncatedEvent from .realtime_audio_config_input_param import RealtimeAudioConfigInputParam as RealtimeAudioConfigInputParam from .realtime_mcp_protocol_error_param import RealtimeMcpProtocolErrorParam as RealtimeMcpProtocolErrorParam from .realtime_mcp_tool_execution_error import RealtimeMcpToolExecutionError as RealtimeMcpToolExecutionError from .realtime_response_create_mcp_tool import RealtimeResponseCreateMcpTool as RealtimeResponseCreateMcpTool from .realtime_tool_choice_config_param import RealtimeToolChoiceConfigParam as RealtimeToolChoiceConfigParam from .realtime_tools_config_union_param import RealtimeToolsConfigUnionParam as RealtimeToolsConfigUnionParam from .response_content_part_added_event import ResponseContentPartAddedEvent as ResponseContentPartAddedEvent from .response_mcp_call_arguments_delta import ResponseMcpCallArgumentsDelta as ResponseMcpCallArgumentsDelta from .input_audio_buffer_committed_event import InputAudioBufferCommittedEvent as InputAudioBufferCommittedEvent from .realtime_audio_config_output_param import RealtimeAudioConfigOutputParam as RealtimeAudioConfigOutputParam from .realtime_audio_input_turn_detection import RealtimeAudioInputTurnDetection as RealtimeAudioInputTurnDetection from .realtime_mcp_approval_request_param import RealtimeMcpApprovalRequestParam as RealtimeMcpApprovalRequestParam from .realtime_truncation_retention_ratio import RealtimeTruncationRetentionRatio as RealtimeTruncationRetentionRatio from .conversation_item_create_event_param import ConversationItemCreateEventParam as ConversationItemCreateEventParam from .conversation_item_delete_event_param import ConversationItemDeleteEventParam as ConversationItemDeleteEventParam from .input_audio_buffer_clear_event_param import InputAudioBufferClearEventParam as InputAudioBufferClearEventParam from .input_audio_buffer_timeout_triggered import InputAudioBufferTimeoutTriggered as InputAudioBufferTimeoutTriggered from .realtime_mcp_approval_response_param import RealtimeMcpApprovalResponseParam as RealtimeMcpApprovalResponseParam from .realtime_transcription_session_audio import RealtimeTranscriptionSessionAudio as RealtimeTranscriptionSessionAudio from .response_audio_transcript_done_event import ResponseAudioTranscriptDoneEvent as ResponseAudioTranscriptDoneEvent from .input_audio_buffer_append_event_param import InputAudioBufferAppendEventParam as InputAudioBufferAppendEventParam from .input_audio_buffer_commit_event_param import InputAudioBufferCommitEventParam as InputAudioBufferCommitEventParam from .output_audio_buffer_clear_event_param import OutputAudioBufferClearEventParam as OutputAudioBufferClearEventParam from .realtime_response_create_audio_output import ( RealtimeResponseCreateAudioOutput as RealtimeResponseCreateAudioOutput, ) from .realtime_response_create_params_param import ( RealtimeResponseCreateParamsParam as RealtimeResponseCreateParamsParam, ) from .realtime_session_create_request_param import ( RealtimeSessionCreateRequestParam as RealtimeSessionCreateRequestParam, ) from .response_audio_transcript_delta_event import ( ResponseAudioTranscriptDeltaEvent as ResponseAudioTranscriptDeltaEvent, ) from .conversation_item_retrieve_event_param import ( ConversationItemRetrieveEventParam as ConversationItemRetrieveEventParam, ) from .conversation_item_truncate_event_param import ( ConversationItemTruncateEventParam as ConversationItemTruncateEventParam, ) from .input_audio_buffer_speech_started_event import ( InputAudioBufferSpeechStartedEvent as InputAudioBufferSpeechStartedEvent, ) from .input_audio_buffer_speech_stopped_event import ( InputAudioBufferSpeechStoppedEvent as InputAudioBufferSpeechStoppedEvent, ) from .realtime_conversation_item_user_message import ( RealtimeConversationItemUserMessage as RealtimeConversationItemUserMessage, ) from .realtime_mcp_tool_execution_error_param import ( RealtimeMcpToolExecutionErrorParam as RealtimeMcpToolExecutionErrorParam, ) from .realtime_response_create_mcp_tool_param import ( RealtimeResponseCreateMcpToolParam as RealtimeResponseCreateMcpToolParam, ) from .realtime_conversation_item_function_call import ( RealtimeConversationItemFunctionCall as RealtimeConversationItemFunctionCall, ) from .realtime_audio_input_turn_detection_param import ( RealtimeAudioInputTurnDetectionParam as RealtimeAudioInputTurnDetectionParam, ) from .realtime_conversation_item_system_message import ( RealtimeConversationItemSystemMessage as RealtimeConversationItemSystemMessage, ) from .realtime_truncation_retention_ratio_param import ( RealtimeTruncationRetentionRatioParam as RealtimeTruncationRetentionRatioParam, ) from .realtime_transcription_session_audio_input import ( RealtimeTranscriptionSessionAudioInput as RealtimeTranscriptionSessionAudioInput, ) from .realtime_transcription_session_audio_param import ( RealtimeTranscriptionSessionAudioParam as RealtimeTranscriptionSessionAudioParam, ) from .realtime_response_create_audio_output_param import ( RealtimeResponseCreateAudioOutputParam as RealtimeResponseCreateAudioOutputParam, ) from .realtime_response_usage_input_token_details import ( RealtimeResponseUsageInputTokenDetails as RealtimeResponseUsageInputTokenDetails, ) from .response_function_call_arguments_done_event import ( ResponseFunctionCallArgumentsDoneEvent as ResponseFunctionCallArgumentsDoneEvent, ) from .input_audio_buffer_dtmf_event_received_event import ( InputAudioBufferDtmfEventReceivedEvent as InputAudioBufferDtmfEventReceivedEvent, ) from .realtime_conversation_item_assistant_message import ( RealtimeConversationItemAssistantMessage as RealtimeConversationItemAssistantMessage, ) from .realtime_response_usage_output_token_details import ( RealtimeResponseUsageOutputTokenDetails as RealtimeResponseUsageOutputTokenDetails, ) from .response_function_call_arguments_delta_event import ( ResponseFunctionCallArgumentsDeltaEvent as ResponseFunctionCallArgumentsDeltaEvent, ) from .realtime_conversation_item_user_message_param import ( RealtimeConversationItemUserMessageParam as RealtimeConversationItemUserMessageParam, ) from .realtime_transcription_session_create_request import ( RealtimeTranscriptionSessionCreateRequest as RealtimeTranscriptionSessionCreateRequest, ) from .realtime_transcription_session_turn_detection import ( RealtimeTranscriptionSessionTurnDetection as RealtimeTranscriptionSessionTurnDetection, ) from .realtime_conversation_item_function_call_param import ( RealtimeConversationItemFunctionCallParam as RealtimeConversationItemFunctionCallParam, ) from .realtime_transcription_session_create_response import ( RealtimeTranscriptionSessionCreateResponse as RealtimeTranscriptionSessionCreateResponse, ) from .realtime_conversation_item_function_call_output import ( RealtimeConversationItemFunctionCallOutput as RealtimeConversationItemFunctionCallOutput, ) from .realtime_conversation_item_system_message_param import ( RealtimeConversationItemSystemMessageParam as RealtimeConversationItemSystemMessageParam, ) from .realtime_transcription_session_audio_input_param import ( RealtimeTranscriptionSessionAudioInputParam as RealtimeTranscriptionSessionAudioInputParam, ) from .realtime_conversation_item_assistant_message_param import ( RealtimeConversationItemAssistantMessageParam as RealtimeConversationItemAssistantMessageParam, ) from .conversation_item_input_audio_transcription_segment import ( ConversationItemInputAudioTranscriptionSegment as ConversationItemInputAudioTranscriptionSegment, ) from .realtime_transcription_session_create_request_param import ( RealtimeTranscriptionSessionCreateRequestParam as RealtimeTranscriptionSessionCreateRequestParam, ) from .realtime_conversation_item_function_call_output_param import ( RealtimeConversationItemFunctionCallOutputParam as RealtimeConversationItemFunctionCallOutputParam, ) from .conversation_item_input_audio_transcription_delta_event import ( ConversationItemInputAudioTranscriptionDeltaEvent as ConversationItemInputAudioTranscriptionDeltaEvent, ) from .conversation_item_input_audio_transcription_failed_event import ( ConversationItemInputAudioTranscriptionFailedEvent as ConversationItemInputAudioTranscriptionFailedEvent, ) from .realtime_transcription_session_audio_input_turn_detection import ( RealtimeTranscriptionSessionAudioInputTurnDetection as RealtimeTranscriptionSessionAudioInputTurnDetection, ) from .conversation_item_input_audio_transcription_completed_event import ( ConversationItemInputAudioTranscriptionCompletedEvent as ConversationItemInputAudioTranscriptionCompletedEvent, ) from .realtime_transcription_session_audio_input_turn_detection_param import ( RealtimeTranscriptionSessionAudioInputTurnDetectionParam as RealtimeTranscriptionSessionAudioInputTurnDetectionParam, ) ================================================ FILE: src/openai/types/realtime/audio_transcription.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["AudioTranscription"] class AudioTranscription(BaseModel): language: Optional[str] = None """The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format will improve accuracy and latency. """ model: Union[ str, Literal[ "whisper-1", "gpt-4o-mini-transcribe", "gpt-4o-mini-transcribe-2025-12-15", "gpt-4o-transcribe", "gpt-4o-transcribe-diarize", ], None, ] = None """The model to use for transcription. Current options are `whisper-1`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `gpt-4o-transcribe`, and `gpt-4o-transcribe-diarize`. Use `gpt-4o-transcribe-diarize` when you need diarization with speaker labels. """ prompt: Optional[str] = None """ An optional text to guide the model's style or continue a previous audio segment. For `whisper-1`, the [prompt is a list of keywords](https://platform.openai.com/docs/guides/speech-to-text#prompting). For `gpt-4o-transcribe` models (excluding `gpt-4o-transcribe-diarize`), the prompt is a free text string, for example "expect words related to technology". """ ================================================ FILE: src/openai/types/realtime/audio_transcription_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, TypedDict __all__ = ["AudioTranscriptionParam"] class AudioTranscriptionParam(TypedDict, total=False): language: str """The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format will improve accuracy and latency. """ model: Union[ str, Literal[ "whisper-1", "gpt-4o-mini-transcribe", "gpt-4o-mini-transcribe-2025-12-15", "gpt-4o-transcribe", "gpt-4o-transcribe-diarize", ], ] """The model to use for transcription. Current options are `whisper-1`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `gpt-4o-transcribe`, and `gpt-4o-transcribe-diarize`. Use `gpt-4o-transcribe-diarize` when you need diarization with speaker labels. """ prompt: str """ An optional text to guide the model's style or continue a previous audio segment. For `whisper-1`, the [prompt is a list of keywords](https://platform.openai.com/docs/guides/speech-to-text#prompting). For `gpt-4o-transcribe` models (excluding `gpt-4o-transcribe-diarize`), the prompt is a free text string, for example "expect words related to technology". """ ================================================ FILE: src/openai/types/realtime/call_accept_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List, Union, Optional from typing_extensions import Literal, Required, TypedDict from .realtime_truncation_param import RealtimeTruncationParam from .realtime_audio_config_param import RealtimeAudioConfigParam from .realtime_tools_config_param import RealtimeToolsConfigParam from .realtime_tracing_config_param import RealtimeTracingConfigParam from ..responses.response_prompt_param import ResponsePromptParam from .realtime_tool_choice_config_param import RealtimeToolChoiceConfigParam __all__ = ["CallAcceptParams"] class CallAcceptParams(TypedDict, total=False): type: Required[Literal["realtime"]] """The type of session to create. Always `realtime` for the Realtime API.""" audio: RealtimeAudioConfigParam """Configuration for input and output audio.""" include: List[Literal["item.input_audio_transcription.logprobs"]] """Additional fields to include in server outputs. `item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription. """ instructions: str """The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. "be extremely succinct", "act friendly", "here are examples of good responses") and on audio behavior (e.g. "talk quickly", "inject emotion into your voice", "laugh frequently"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior. Note that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session. """ max_output_tokens: Union[int, Literal["inf"]] """ Maximum number of output tokens for a single assistant response, inclusive of tool calls. Provide an integer between 1 and 4096 to limit output tokens, or `inf` for the maximum available tokens for a given model. Defaults to `inf`. """ model: Union[ str, Literal[ "gpt-realtime", "gpt-realtime-1.5", "gpt-realtime-2025-08-28", "gpt-4o-realtime-preview", "gpt-4o-realtime-preview-2024-10-01", "gpt-4o-realtime-preview-2024-12-17", "gpt-4o-realtime-preview-2025-06-03", "gpt-4o-mini-realtime-preview", "gpt-4o-mini-realtime-preview-2024-12-17", "gpt-realtime-mini", "gpt-realtime-mini-2025-10-06", "gpt-realtime-mini-2025-12-15", "gpt-audio-1.5", "gpt-audio-mini", "gpt-audio-mini-2025-10-06", "gpt-audio-mini-2025-12-15", ], ] """The Realtime model used for this session.""" output_modalities: List[Literal["text", "audio"]] """The set of modalities the model can respond with. It defaults to `["audio"]`, indicating that the model will respond with audio plus a transcript. `["text"]` can be used to make the model respond with text only. It is not possible to request both `text` and `audio` at the same time. """ prompt: Optional[ResponsePromptParam] """ Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). """ tool_choice: RealtimeToolChoiceConfigParam """How the model chooses tools. Provide one of the string modes or force a specific function/MCP tool. """ tools: RealtimeToolsConfigParam """Tools available to the model.""" tracing: Optional[RealtimeTracingConfigParam] """ Realtime API can write session traces to the [Traces Dashboard](/logs?api=traces). Set to null to disable tracing. Once tracing is enabled for a session, the configuration cannot be modified. `auto` will create a trace for the session with default values for the workflow name, group id, and metadata. """ truncation: RealtimeTruncationParam """ When the number of tokens in a conversation exceeds the model's input token limit, the conversation be truncated, meaning messages (starting from the oldest) will not be included in the model's context. A 32k context model with 4,096 max output tokens can only include 28,224 tokens in the context before truncation occurs. Clients can configure truncation behavior to truncate with a lower max token limit, which is an effective way to control token usage and cost. Truncation will reduce the number of cached tokens on the next turn (busting the cache), since messages are dropped from the beginning of the context. However, clients can also configure truncation to retain messages up to a fraction of the maximum context size, which will reduce the need for future truncations and thus improve the cache rate. Truncation can be disabled entirely, which means the server will never truncate but would instead return an error if the conversation exceeds the model's input token limit. """ ================================================ FILE: src/openai/types/realtime/call_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Required, TypedDict from .realtime_session_create_request_param import RealtimeSessionCreateRequestParam __all__ = ["CallCreateParams"] class CallCreateParams(TypedDict, total=False): sdp: Required[str] """WebRTC Session Description Protocol (SDP) offer generated by the caller.""" session: RealtimeSessionCreateRequestParam """Realtime session object configuration.""" ================================================ FILE: src/openai/types/realtime/call_refer_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Required, TypedDict __all__ = ["CallReferParams"] class CallReferParams(TypedDict, total=False): target_uri: Required[str] """URI that should appear in the SIP Refer-To header. Supports values like `tel:+14155550123` or `sip:agent@example.com`. """ ================================================ FILE: src/openai/types/realtime/call_reject_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import TypedDict __all__ = ["CallRejectParams"] class CallRejectParams(TypedDict, total=False): status_code: int """SIP response code to send back to the caller. Defaults to `603` (Decline) when omitted. """ ================================================ FILE: src/openai/types/realtime/client_secret_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, TypeAlias, TypedDict from .realtime_session_create_request_param import RealtimeSessionCreateRequestParam from .realtime_transcription_session_create_request_param import RealtimeTranscriptionSessionCreateRequestParam __all__ = ["ClientSecretCreateParams", "ExpiresAfter", "Session"] class ClientSecretCreateParams(TypedDict, total=False): expires_after: ExpiresAfter """Configuration for the client secret expiration. Expiration refers to the time after which a client secret will no longer be valid for creating sessions. The session itself may continue after that time once started. A secret can be used to create multiple sessions until it expires. """ session: Session """Session configuration to use for the client secret. Choose either a realtime session or a transcription session. """ class ExpiresAfter(TypedDict, total=False): """Configuration for the client secret expiration. Expiration refers to the time after which a client secret will no longer be valid for creating sessions. The session itself may continue after that time once started. A secret can be used to create multiple sessions until it expires. """ anchor: Literal["created_at"] """ The anchor point for the client secret expiration, meaning that `seconds` will be added to the `created_at` time of the client secret to produce an expiration timestamp. Only `created_at` is currently supported. """ seconds: int """The number of seconds from the anchor point to the expiration. Select a value between `10` and `7200` (2 hours). This default to 600 seconds (10 minutes) if not specified. """ Session: TypeAlias = Union[RealtimeSessionCreateRequestParam, RealtimeTranscriptionSessionCreateRequestParam] ================================================ FILE: src/openai/types/realtime/client_secret_create_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .realtime_session_create_response import RealtimeSessionCreateResponse from .realtime_transcription_session_create_response import RealtimeTranscriptionSessionCreateResponse __all__ = ["ClientSecretCreateResponse", "Session"] Session: TypeAlias = Annotated[ Union[RealtimeSessionCreateResponse, RealtimeTranscriptionSessionCreateResponse], PropertyInfo(discriminator="type") ] class ClientSecretCreateResponse(BaseModel): """Response from creating a session and client secret for the Realtime API.""" expires_at: int """Expiration timestamp for the client secret, in seconds since epoch.""" session: Session """The session configuration for either a realtime or transcription session.""" value: str """The generated client secret value.""" ================================================ FILE: src/openai/types/realtime/conversation_created_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ConversationCreatedEvent", "Conversation"] class Conversation(BaseModel): """The conversation resource.""" id: Optional[str] = None """The unique ID of the conversation.""" object: Optional[Literal["realtime.conversation"]] = None """The object type, must be `realtime.conversation`.""" class ConversationCreatedEvent(BaseModel): """Returned when a conversation is created. Emitted right after session creation.""" conversation: Conversation """The conversation resource.""" event_id: str """The unique ID of the server event.""" type: Literal["conversation.created"] """The event type, must be `conversation.created`.""" ================================================ FILE: src/openai/types/realtime/conversation_item.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from ..._utils import PropertyInfo from .realtime_mcp_tool_call import RealtimeMcpToolCall from .realtime_mcp_list_tools import RealtimeMcpListTools from .realtime_mcp_approval_request import RealtimeMcpApprovalRequest from .realtime_mcp_approval_response import RealtimeMcpApprovalResponse from .realtime_conversation_item_user_message import RealtimeConversationItemUserMessage from .realtime_conversation_item_function_call import RealtimeConversationItemFunctionCall from .realtime_conversation_item_system_message import RealtimeConversationItemSystemMessage from .realtime_conversation_item_assistant_message import RealtimeConversationItemAssistantMessage from .realtime_conversation_item_function_call_output import RealtimeConversationItemFunctionCallOutput __all__ = ["ConversationItem"] ConversationItem: TypeAlias = Annotated[ Union[ RealtimeConversationItemSystemMessage, RealtimeConversationItemUserMessage, RealtimeConversationItemAssistantMessage, RealtimeConversationItemFunctionCall, RealtimeConversationItemFunctionCallOutput, RealtimeMcpApprovalResponse, RealtimeMcpListTools, RealtimeMcpToolCall, RealtimeMcpApprovalRequest, ], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/types/realtime/conversation_item_added.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel from .conversation_item import ConversationItem __all__ = ["ConversationItemAdded"] class ConversationItemAdded(BaseModel): """Sent by the server when an Item is added to the default Conversation. This can happen in several cases: - When the client sends a `conversation.item.create` event. - When the input audio buffer is committed. In this case the item will be a user message containing the audio from the buffer. - When the model is generating a Response. In this case the `conversation.item.added` event will be sent when the model starts generating a specific Item, and thus it will not yet have any content (and `status` will be `in_progress`). The event will include the full content of the Item (except when model is generating a Response) except for audio data, which can be retrieved separately with a `conversation.item.retrieve` event if necessary. """ event_id: str """The unique ID of the server event.""" item: ConversationItem """A single item within a Realtime conversation.""" type: Literal["conversation.item.added"] """The event type, must be `conversation.item.added`.""" previous_item_id: Optional[str] = None """The ID of the item that precedes this one, if any. This is used to maintain ordering when items are inserted. """ ================================================ FILE: src/openai/types/realtime/conversation_item_create_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel from .conversation_item import ConversationItem __all__ = ["ConversationItemCreateEvent"] class ConversationItemCreateEvent(BaseModel): """ Add a new Item to the Conversation's context, including messages, function calls, and function call responses. This event can be used both to populate a "history" of the conversation and to add new items mid-stream, but has the current limitation that it cannot populate assistant audio messages. If successful, the server will respond with a `conversation.item.created` event, otherwise an `error` event will be sent. """ item: ConversationItem """A single item within a Realtime conversation.""" type: Literal["conversation.item.create"] """The event type, must be `conversation.item.create`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" previous_item_id: Optional[str] = None """The ID of the preceding item after which the new item will be inserted. If not set, the new item will be appended to the end of the conversation. If set to `root`, the new item will be added to the beginning of the conversation. If set to an existing ID, it allows an item to be inserted mid-conversation. If the ID cannot be found, an error will be returned and the item will not be added. """ ================================================ FILE: src/openai/types/realtime/conversation_item_create_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict from .conversation_item_param import ConversationItemParam __all__ = ["ConversationItemCreateEventParam"] class ConversationItemCreateEventParam(TypedDict, total=False): """ Add a new Item to the Conversation's context, including messages, function calls, and function call responses. This event can be used both to populate a "history" of the conversation and to add new items mid-stream, but has the current limitation that it cannot populate assistant audio messages. If successful, the server will respond with a `conversation.item.created` event, otherwise an `error` event will be sent. """ item: Required[ConversationItemParam] """A single item within a Realtime conversation.""" type: Required[Literal["conversation.item.create"]] """The event type, must be `conversation.item.create`.""" event_id: str """Optional client-generated ID used to identify this event.""" previous_item_id: str """The ID of the preceding item after which the new item will be inserted. If not set, the new item will be appended to the end of the conversation. If set to `root`, the new item will be added to the beginning of the conversation. If set to an existing ID, it allows an item to be inserted mid-conversation. If the ID cannot be found, an error will be returned and the item will not be added. """ ================================================ FILE: src/openai/types/realtime/conversation_item_created_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel from .conversation_item import ConversationItem __all__ = ["ConversationItemCreatedEvent"] class ConversationItemCreatedEvent(BaseModel): """Returned when a conversation item is created. There are several scenarios that produce this event: - The server is generating a Response, which if successful will produce either one or two Items, which will be of type `message` (role `assistant`) or type `function_call`. - The input audio buffer has been committed, either by the client or the server (in `server_vad` mode). The server will take the content of the input audio buffer and add it to a new user message Item. - The client has sent a `conversation.item.create` event to add a new Item to the Conversation. """ event_id: str """The unique ID of the server event.""" item: ConversationItem """A single item within a Realtime conversation.""" type: Literal["conversation.item.created"] """The event type, must be `conversation.item.created`.""" previous_item_id: Optional[str] = None """ The ID of the preceding item in the Conversation context, allows the client to understand the order of the conversation. Can be `null` if the item has no predecessor. """ ================================================ FILE: src/openai/types/realtime/conversation_item_delete_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ConversationItemDeleteEvent"] class ConversationItemDeleteEvent(BaseModel): """Send this event when you want to remove any item from the conversation history. The server will respond with a `conversation.item.deleted` event, unless the item does not exist in the conversation history, in which case the server will respond with an error. """ item_id: str """The ID of the item to delete.""" type: Literal["conversation.item.delete"] """The event type, must be `conversation.item.delete`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/realtime/conversation_item_delete_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ConversationItemDeleteEventParam"] class ConversationItemDeleteEventParam(TypedDict, total=False): """Send this event when you want to remove any item from the conversation history. The server will respond with a `conversation.item.deleted` event, unless the item does not exist in the conversation history, in which case the server will respond with an error. """ item_id: Required[str] """The ID of the item to delete.""" type: Required[Literal["conversation.item.delete"]] """The event type, must be `conversation.item.delete`.""" event_id: str """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/realtime/conversation_item_deleted_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ConversationItemDeletedEvent"] class ConversationItemDeletedEvent(BaseModel): """ Returned when an item in the conversation is deleted by the client with a `conversation.item.delete` event. This event is used to synchronize the server's understanding of the conversation history with the client's view. """ event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item that was deleted.""" type: Literal["conversation.item.deleted"] """The event type, must be `conversation.item.deleted`.""" ================================================ FILE: src/openai/types/realtime/conversation_item_done.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel from .conversation_item import ConversationItem __all__ = ["ConversationItemDone"] class ConversationItemDone(BaseModel): """Returned when a conversation item is finalized. The event will include the full content of the Item except for audio data, which can be retrieved separately with a `conversation.item.retrieve` event if needed. """ event_id: str """The unique ID of the server event.""" item: ConversationItem """A single item within a Realtime conversation.""" type: Literal["conversation.item.done"] """The event type, must be `conversation.item.done`.""" previous_item_id: Optional[str] = None """The ID of the item that precedes this one, if any. This is used to maintain ordering when items are inserted. """ ================================================ FILE: src/openai/types/realtime/conversation_item_input_audio_transcription_completed_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, TypeAlias from ..._models import BaseModel from .log_prob_properties import LogProbProperties __all__ = [ "ConversationItemInputAudioTranscriptionCompletedEvent", "Usage", "UsageTranscriptTextUsageTokens", "UsageTranscriptTextUsageTokensInputTokenDetails", "UsageTranscriptTextUsageDuration", ] class UsageTranscriptTextUsageTokensInputTokenDetails(BaseModel): """Details about the input tokens billed for this request.""" audio_tokens: Optional[int] = None """Number of audio tokens billed for this request.""" text_tokens: Optional[int] = None """Number of text tokens billed for this request.""" class UsageTranscriptTextUsageTokens(BaseModel): """Usage statistics for models billed by token usage.""" input_tokens: int """Number of input tokens billed for this request.""" output_tokens: int """Number of output tokens generated.""" total_tokens: int """Total number of tokens used (input + output).""" type: Literal["tokens"] """The type of the usage object. Always `tokens` for this variant.""" input_token_details: Optional[UsageTranscriptTextUsageTokensInputTokenDetails] = None """Details about the input tokens billed for this request.""" class UsageTranscriptTextUsageDuration(BaseModel): """Usage statistics for models billed by audio input duration.""" seconds: float """Duration of the input audio in seconds.""" type: Literal["duration"] """The type of the usage object. Always `duration` for this variant.""" Usage: TypeAlias = Union[UsageTranscriptTextUsageTokens, UsageTranscriptTextUsageDuration] class ConversationItemInputAudioTranscriptionCompletedEvent(BaseModel): """ This event is the output of audio transcription for user audio written to the user audio buffer. Transcription begins when the input audio buffer is committed by the client or server (when VAD is enabled). Transcription runs asynchronously with Response creation, so this event may come before or after the Response events. Realtime API models accept audio natively, and thus input transcription is a separate process run on a separate ASR (Automatic Speech Recognition) model. The transcript may diverge somewhat from the model's interpretation, and should be treated as a rough guide. """ content_index: int """The index of the content part containing the audio.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item containing the audio that is being transcribed.""" transcript: str """The transcribed text.""" type: Literal["conversation.item.input_audio_transcription.completed"] """ The event type, must be `conversation.item.input_audio_transcription.completed`. """ usage: Usage """ Usage statistics for the transcription, this is billed according to the ASR model's pricing rather than the realtime model's pricing. """ logprobs: Optional[List[LogProbProperties]] = None """The log probabilities of the transcription.""" ================================================ FILE: src/openai/types/realtime/conversation_item_input_audio_transcription_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel from .log_prob_properties import LogProbProperties __all__ = ["ConversationItemInputAudioTranscriptionDeltaEvent"] class ConversationItemInputAudioTranscriptionDeltaEvent(BaseModel): """ Returned when the text value of an input audio transcription content part is updated with incremental transcription results. """ event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item containing the audio that is being transcribed.""" type: Literal["conversation.item.input_audio_transcription.delta"] """The event type, must be `conversation.item.input_audio_transcription.delta`.""" content_index: Optional[int] = None """The index of the content part in the item's content array.""" delta: Optional[str] = None """The text delta.""" logprobs: Optional[List[LogProbProperties]] = None """The log probabilities of the transcription. These can be enabled by configurating the session with `"include": ["item.input_audio_transcription.logprobs"]`. Each entry in the array corresponds a log probability of which token would be selected for this chunk of transcription. This can help to identify if it was possible there were multiple valid options for a given chunk of transcription. """ ================================================ FILE: src/openai/types/realtime/conversation_item_input_audio_transcription_failed_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ConversationItemInputAudioTranscriptionFailedEvent", "Error"] class Error(BaseModel): """Details of the transcription error.""" code: Optional[str] = None """Error code, if any.""" message: Optional[str] = None """A human-readable error message.""" param: Optional[str] = None """Parameter related to the error, if any.""" type: Optional[str] = None """The type of error.""" class ConversationItemInputAudioTranscriptionFailedEvent(BaseModel): """ Returned when input audio transcription is configured, and a transcription request for a user message failed. These events are separate from other `error` events so that the client can identify the related Item. """ content_index: int """The index of the content part containing the audio.""" error: Error """Details of the transcription error.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the user message item.""" type: Literal["conversation.item.input_audio_transcription.failed"] """The event type, must be `conversation.item.input_audio_transcription.failed`.""" ================================================ FILE: src/openai/types/realtime/conversation_item_input_audio_transcription_segment.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ConversationItemInputAudioTranscriptionSegment"] class ConversationItemInputAudioTranscriptionSegment(BaseModel): """Returned when an input audio transcription segment is identified for an item.""" id: str """The segment identifier.""" content_index: int """The index of the input audio content part within the item.""" end: float """End time of the segment in seconds.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item containing the input audio content.""" speaker: str """The detected speaker label for this segment.""" start: float """Start time of the segment in seconds.""" text: str """The text for this segment.""" type: Literal["conversation.item.input_audio_transcription.segment"] """The event type, must be `conversation.item.input_audio_transcription.segment`.""" ================================================ FILE: src/openai/types/realtime/conversation_item_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import TypeAlias from .realtime_mcp_tool_call_param import RealtimeMcpToolCallParam from .realtime_mcp_list_tools_param import RealtimeMcpListToolsParam from .realtime_mcp_approval_request_param import RealtimeMcpApprovalRequestParam from .realtime_mcp_approval_response_param import RealtimeMcpApprovalResponseParam from .realtime_conversation_item_user_message_param import RealtimeConversationItemUserMessageParam from .realtime_conversation_item_function_call_param import RealtimeConversationItemFunctionCallParam from .realtime_conversation_item_system_message_param import RealtimeConversationItemSystemMessageParam from .realtime_conversation_item_assistant_message_param import RealtimeConversationItemAssistantMessageParam from .realtime_conversation_item_function_call_output_param import RealtimeConversationItemFunctionCallOutputParam __all__ = ["ConversationItemParam"] ConversationItemParam: TypeAlias = Union[ RealtimeConversationItemSystemMessageParam, RealtimeConversationItemUserMessageParam, RealtimeConversationItemAssistantMessageParam, RealtimeConversationItemFunctionCallParam, RealtimeConversationItemFunctionCallOutputParam, RealtimeMcpApprovalResponseParam, RealtimeMcpListToolsParam, RealtimeMcpToolCallParam, RealtimeMcpApprovalRequestParam, ] ================================================ FILE: src/openai/types/realtime/conversation_item_retrieve_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ConversationItemRetrieveEvent"] class ConversationItemRetrieveEvent(BaseModel): """ Send this event when you want to retrieve the server's representation of a specific item in the conversation history. This is useful, for example, to inspect user audio after noise cancellation and VAD. The server will respond with a `conversation.item.retrieved` event, unless the item does not exist in the conversation history, in which case the server will respond with an error. """ item_id: str """The ID of the item to retrieve.""" type: Literal["conversation.item.retrieve"] """The event type, must be `conversation.item.retrieve`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/realtime/conversation_item_retrieve_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ConversationItemRetrieveEventParam"] class ConversationItemRetrieveEventParam(TypedDict, total=False): """ Send this event when you want to retrieve the server's representation of a specific item in the conversation history. This is useful, for example, to inspect user audio after noise cancellation and VAD. The server will respond with a `conversation.item.retrieved` event, unless the item does not exist in the conversation history, in which case the server will respond with an error. """ item_id: Required[str] """The ID of the item to retrieve.""" type: Required[Literal["conversation.item.retrieve"]] """The event type, must be `conversation.item.retrieve`.""" event_id: str """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/realtime/conversation_item_truncate_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ConversationItemTruncateEvent"] class ConversationItemTruncateEvent(BaseModel): """Send this event to truncate a previous assistant message’s audio. The server will produce audio faster than realtime, so this event is useful when the user interrupts to truncate audio that has already been sent to the client but not yet played. This will synchronize the server's understanding of the audio with the client's playback. Truncating audio will delete the server-side text transcript to ensure there is not text in the context that hasn't been heard by the user. If successful, the server will respond with a `conversation.item.truncated` event. """ audio_end_ms: int """Inclusive duration up to which audio is truncated, in milliseconds. If the audio_end_ms is greater than the actual audio duration, the server will respond with an error. """ content_index: int """The index of the content part to truncate. Set this to `0`.""" item_id: str """The ID of the assistant message item to truncate. Only assistant message items can be truncated. """ type: Literal["conversation.item.truncate"] """The event type, must be `conversation.item.truncate`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/realtime/conversation_item_truncate_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ConversationItemTruncateEventParam"] class ConversationItemTruncateEventParam(TypedDict, total=False): """Send this event to truncate a previous assistant message’s audio. The server will produce audio faster than realtime, so this event is useful when the user interrupts to truncate audio that has already been sent to the client but not yet played. This will synchronize the server's understanding of the audio with the client's playback. Truncating audio will delete the server-side text transcript to ensure there is not text in the context that hasn't been heard by the user. If successful, the server will respond with a `conversation.item.truncated` event. """ audio_end_ms: Required[int] """Inclusive duration up to which audio is truncated, in milliseconds. If the audio_end_ms is greater than the actual audio duration, the server will respond with an error. """ content_index: Required[int] """The index of the content part to truncate. Set this to `0`.""" item_id: Required[str] """The ID of the assistant message item to truncate. Only assistant message items can be truncated. """ type: Required[Literal["conversation.item.truncate"]] """The event type, must be `conversation.item.truncate`.""" event_id: str """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/realtime/conversation_item_truncated_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ConversationItemTruncatedEvent"] class ConversationItemTruncatedEvent(BaseModel): """ Returned when an earlier assistant audio message item is truncated by the client with a `conversation.item.truncate` event. This event is used to synchronize the server's understanding of the audio with the client's playback. This action will truncate the audio and remove the server-side text transcript to ensure there is no text in the context that hasn't been heard by the user. """ audio_end_ms: int """The duration up to which the audio was truncated, in milliseconds.""" content_index: int """The index of the content part that was truncated.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the assistant message item that was truncated.""" type: Literal["conversation.item.truncated"] """The event type, must be `conversation.item.truncated`.""" ================================================ FILE: src/openai/types/realtime/input_audio_buffer_append_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["InputAudioBufferAppendEvent"] class InputAudioBufferAppendEvent(BaseModel): """Send this event to append audio bytes to the input audio buffer. The audio buffer is temporary storage you can write to and later commit. A "commit" will create a new user message item in the conversation history from the buffer content and clear the buffer. Input audio transcription (if enabled) will be generated when the buffer is committed. If VAD is enabled the audio buffer is used to detect speech and the server will decide when to commit. When Server VAD is disabled, you must commit the audio buffer manually. Input audio noise reduction operates on writes to the audio buffer. The client may choose how much audio to place in each event up to a maximum of 15 MiB, for example streaming smaller chunks from the client may allow the VAD to be more responsive. Unlike most other client events, the server will not send a confirmation response to this event. """ audio: str """Base64-encoded audio bytes. This must be in the format specified by the `input_audio_format` field in the session configuration. """ type: Literal["input_audio_buffer.append"] """The event type, must be `input_audio_buffer.append`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/realtime/input_audio_buffer_append_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["InputAudioBufferAppendEventParam"] class InputAudioBufferAppendEventParam(TypedDict, total=False): """Send this event to append audio bytes to the input audio buffer. The audio buffer is temporary storage you can write to and later commit. A "commit" will create a new user message item in the conversation history from the buffer content and clear the buffer. Input audio transcription (if enabled) will be generated when the buffer is committed. If VAD is enabled the audio buffer is used to detect speech and the server will decide when to commit. When Server VAD is disabled, you must commit the audio buffer manually. Input audio noise reduction operates on writes to the audio buffer. The client may choose how much audio to place in each event up to a maximum of 15 MiB, for example streaming smaller chunks from the client may allow the VAD to be more responsive. Unlike most other client events, the server will not send a confirmation response to this event. """ audio: Required[str] """Base64-encoded audio bytes. This must be in the format specified by the `input_audio_format` field in the session configuration. """ type: Required[Literal["input_audio_buffer.append"]] """The event type, must be `input_audio_buffer.append`.""" event_id: str """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/realtime/input_audio_buffer_clear_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["InputAudioBufferClearEvent"] class InputAudioBufferClearEvent(BaseModel): """Send this event to clear the audio bytes in the buffer. The server will respond with an `input_audio_buffer.cleared` event. """ type: Literal["input_audio_buffer.clear"] """The event type, must be `input_audio_buffer.clear`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/realtime/input_audio_buffer_clear_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["InputAudioBufferClearEventParam"] class InputAudioBufferClearEventParam(TypedDict, total=False): """Send this event to clear the audio bytes in the buffer. The server will respond with an `input_audio_buffer.cleared` event. """ type: Required[Literal["input_audio_buffer.clear"]] """The event type, must be `input_audio_buffer.clear`.""" event_id: str """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/realtime/input_audio_buffer_cleared_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["InputAudioBufferClearedEvent"] class InputAudioBufferClearedEvent(BaseModel): """ Returned when the input audio buffer is cleared by the client with a `input_audio_buffer.clear` event. """ event_id: str """The unique ID of the server event.""" type: Literal["input_audio_buffer.cleared"] """The event type, must be `input_audio_buffer.cleared`.""" ================================================ FILE: src/openai/types/realtime/input_audio_buffer_commit_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["InputAudioBufferCommitEvent"] class InputAudioBufferCommitEvent(BaseModel): """ Send this event to commit the user input audio buffer, which will create a new user message item in the conversation. This event will produce an error if the input audio buffer is empty. When in Server VAD mode, the client does not need to send this event, the server will commit the audio buffer automatically. Committing the input audio buffer will trigger input audio transcription (if enabled in session configuration), but it will not create a response from the model. The server will respond with an `input_audio_buffer.committed` event. """ type: Literal["input_audio_buffer.commit"] """The event type, must be `input_audio_buffer.commit`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/realtime/input_audio_buffer_commit_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["InputAudioBufferCommitEventParam"] class InputAudioBufferCommitEventParam(TypedDict, total=False): """ Send this event to commit the user input audio buffer, which will create a new user message item in the conversation. This event will produce an error if the input audio buffer is empty. When in Server VAD mode, the client does not need to send this event, the server will commit the audio buffer automatically. Committing the input audio buffer will trigger input audio transcription (if enabled in session configuration), but it will not create a response from the model. The server will respond with an `input_audio_buffer.committed` event. """ type: Required[Literal["input_audio_buffer.commit"]] """The event type, must be `input_audio_buffer.commit`.""" event_id: str """Optional client-generated ID used to identify this event.""" ================================================ FILE: src/openai/types/realtime/input_audio_buffer_committed_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["InputAudioBufferCommittedEvent"] class InputAudioBufferCommittedEvent(BaseModel): """ Returned when an input audio buffer is committed, either by the client or automatically in server VAD mode. The `item_id` property is the ID of the user message item that will be created, thus a `conversation.item.created` event will also be sent to the client. """ event_id: str """The unique ID of the server event.""" item_id: str """The ID of the user message item that will be created.""" type: Literal["input_audio_buffer.committed"] """The event type, must be `input_audio_buffer.committed`.""" previous_item_id: Optional[str] = None """ The ID of the preceding item after which the new item will be inserted. Can be `null` if the item has no predecessor. """ ================================================ FILE: src/openai/types/realtime/input_audio_buffer_dtmf_event_received_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["InputAudioBufferDtmfEventReceivedEvent"] class InputAudioBufferDtmfEventReceivedEvent(BaseModel): """**SIP Only:** Returned when an DTMF event is received. A DTMF event is a message that represents a telephone keypad press (0–9, *, #, A–D). The `event` property is the keypad that the user press. The `received_at` is the UTC Unix Timestamp that the server received the event. """ event: str """The telephone keypad that was pressed by the user.""" received_at: int """UTC Unix Timestamp when DTMF Event was received by server.""" type: Literal["input_audio_buffer.dtmf_event_received"] """The event type, must be `input_audio_buffer.dtmf_event_received`.""" ================================================ FILE: src/openai/types/realtime/input_audio_buffer_speech_started_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["InputAudioBufferSpeechStartedEvent"] class InputAudioBufferSpeechStartedEvent(BaseModel): """ Sent by the server when in `server_vad` mode to indicate that speech has been detected in the audio buffer. This can happen any time audio is added to the buffer (unless speech is already detected). The client may want to use this event to interrupt audio playback or provide visual feedback to the user. The client should expect to receive a `input_audio_buffer.speech_stopped` event when speech stops. The `item_id` property is the ID of the user message item that will be created when speech stops and will also be included in the `input_audio_buffer.speech_stopped` event (unless the client manually commits the audio buffer during VAD activation). """ audio_start_ms: int """ Milliseconds from the start of all audio written to the buffer during the session when speech was first detected. This will correspond to the beginning of audio sent to the model, and thus includes the `prefix_padding_ms` configured in the Session. """ event_id: str """The unique ID of the server event.""" item_id: str """The ID of the user message item that will be created when speech stops.""" type: Literal["input_audio_buffer.speech_started"] """The event type, must be `input_audio_buffer.speech_started`.""" ================================================ FILE: src/openai/types/realtime/input_audio_buffer_speech_stopped_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["InputAudioBufferSpeechStoppedEvent"] class InputAudioBufferSpeechStoppedEvent(BaseModel): """ Returned in `server_vad` mode when the server detects the end of speech in the audio buffer. The server will also send an `conversation.item.created` event with the user message item that is created from the audio buffer. """ audio_end_ms: int """Milliseconds since the session started when speech stopped. This will correspond to the end of audio sent to the model, and thus includes the `min_silence_duration_ms` configured in the Session. """ event_id: str """The unique ID of the server event.""" item_id: str """The ID of the user message item that will be created.""" type: Literal["input_audio_buffer.speech_stopped"] """The event type, must be `input_audio_buffer.speech_stopped`.""" ================================================ FILE: src/openai/types/realtime/input_audio_buffer_timeout_triggered.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["InputAudioBufferTimeoutTriggered"] class InputAudioBufferTimeoutTriggered(BaseModel): """Returned when the Server VAD timeout is triggered for the input audio buffer. This is configured with `idle_timeout_ms` in the `turn_detection` settings of the session, and it indicates that there hasn't been any speech detected for the configured duration. The `audio_start_ms` and `audio_end_ms` fields indicate the segment of audio after the last model response up to the triggering time, as an offset from the beginning of audio written to the input audio buffer. This means it demarcates the segment of audio that was silent and the difference between the start and end values will roughly match the configured timeout. The empty audio will be committed to the conversation as an `input_audio` item (there will be a `input_audio_buffer.committed` event) and a model response will be generated. There may be speech that didn't trigger VAD but is still detected by the model, so the model may respond with something relevant to the conversation or a prompt to continue speaking. """ audio_end_ms: int """ Millisecond offset of audio written to the input audio buffer at the time the timeout was triggered. """ audio_start_ms: int """ Millisecond offset of audio written to the input audio buffer that was after the playback time of the last model response. """ event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item associated with this segment.""" type: Literal["input_audio_buffer.timeout_triggered"] """The event type, must be `input_audio_buffer.timeout_triggered`.""" ================================================ FILE: src/openai/types/realtime/log_prob_properties.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List from ..._models import BaseModel __all__ = ["LogProbProperties"] class LogProbProperties(BaseModel): """A log probability object.""" token: str """The token that was used to generate the log probability.""" bytes: List[int] """The bytes that were used to generate the log probability.""" logprob: float """The log probability of the token.""" ================================================ FILE: src/openai/types/realtime/mcp_list_tools_completed.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["McpListToolsCompleted"] class McpListToolsCompleted(BaseModel): """Returned when listing MCP tools has completed for an item.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the MCP list tools item.""" type: Literal["mcp_list_tools.completed"] """The event type, must be `mcp_list_tools.completed`.""" ================================================ FILE: src/openai/types/realtime/mcp_list_tools_failed.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["McpListToolsFailed"] class McpListToolsFailed(BaseModel): """Returned when listing MCP tools has failed for an item.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the MCP list tools item.""" type: Literal["mcp_list_tools.failed"] """The event type, must be `mcp_list_tools.failed`.""" ================================================ FILE: src/openai/types/realtime/mcp_list_tools_in_progress.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["McpListToolsInProgress"] class McpListToolsInProgress(BaseModel): """Returned when listing MCP tools is in progress for an item.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the MCP list tools item.""" type: Literal["mcp_list_tools.in_progress"] """The event type, must be `mcp_list_tools.in_progress`.""" ================================================ FILE: src/openai/types/realtime/noise_reduction_type.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["NoiseReductionType"] NoiseReductionType: TypeAlias = Literal["near_field", "far_field"] ================================================ FILE: src/openai/types/realtime/output_audio_buffer_clear_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["OutputAudioBufferClearEvent"] class OutputAudioBufferClearEvent(BaseModel): """**WebRTC/SIP Only:** Emit to cut off the current audio response. This will trigger the server to stop generating audio and emit a `output_audio_buffer.cleared` event. This event should be preceded by a `response.cancel` client event to stop the generation of the current response. [Learn more](https://platform.openai.com/docs/guides/realtime-conversations#client-and-server-events-for-audio-in-webrtc). """ type: Literal["output_audio_buffer.clear"] """The event type, must be `output_audio_buffer.clear`.""" event_id: Optional[str] = None """The unique ID of the client event used for error handling.""" ================================================ FILE: src/openai/types/realtime/output_audio_buffer_clear_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["OutputAudioBufferClearEventParam"] class OutputAudioBufferClearEventParam(TypedDict, total=False): """**WebRTC/SIP Only:** Emit to cut off the current audio response. This will trigger the server to stop generating audio and emit a `output_audio_buffer.cleared` event. This event should be preceded by a `response.cancel` client event to stop the generation of the current response. [Learn more](https://platform.openai.com/docs/guides/realtime-conversations#client-and-server-events-for-audio-in-webrtc). """ type: Required[Literal["output_audio_buffer.clear"]] """The event type, must be `output_audio_buffer.clear`.""" event_id: str """The unique ID of the client event used for error handling.""" ================================================ FILE: src/openai/types/realtime/rate_limits_updated_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["RateLimitsUpdatedEvent", "RateLimit"] class RateLimit(BaseModel): limit: Optional[int] = None """The maximum allowed value for the rate limit.""" name: Optional[Literal["requests", "tokens"]] = None """The name of the rate limit (`requests`, `tokens`).""" remaining: Optional[int] = None """The remaining value before the limit is reached.""" reset_seconds: Optional[float] = None """Seconds until the rate limit resets.""" class RateLimitsUpdatedEvent(BaseModel): """Emitted at the beginning of a Response to indicate the updated rate limits. When a Response is created some tokens will be "reserved" for the output tokens, the rate limits shown here reflect that reservation, which is then adjusted accordingly once the Response is completed. """ event_id: str """The unique ID of the server event.""" rate_limits: List[RateLimit] """List of rate limit information.""" type: Literal["rate_limits.updated"] """The event type, must be `rate_limits.updated`.""" ================================================ FILE: src/openai/types/realtime/realtime_audio_config.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from ..._models import BaseModel from .realtime_audio_config_input import RealtimeAudioConfigInput from .realtime_audio_config_output import RealtimeAudioConfigOutput __all__ = ["RealtimeAudioConfig"] class RealtimeAudioConfig(BaseModel): """Configuration for input and output audio.""" input: Optional[RealtimeAudioConfigInput] = None output: Optional[RealtimeAudioConfigOutput] = None ================================================ FILE: src/openai/types/realtime/realtime_audio_config_input.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from ..._models import BaseModel from .audio_transcription import AudioTranscription from .noise_reduction_type import NoiseReductionType from .realtime_audio_formats import RealtimeAudioFormats from .realtime_audio_input_turn_detection import RealtimeAudioInputTurnDetection __all__ = ["RealtimeAudioConfigInput", "NoiseReduction"] class NoiseReduction(BaseModel): """Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. """ type: Optional[NoiseReductionType] = None """Type of noise reduction. `near_field` is for close-talking microphones such as headphones, `far_field` is for far-field microphones such as laptop or conference room microphones. """ class RealtimeAudioConfigInput(BaseModel): format: Optional[RealtimeAudioFormats] = None """The format of the input audio.""" noise_reduction: Optional[NoiseReduction] = None """Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. """ transcription: Optional[AudioTranscription] = None """ Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](https://platform.openai.com/docs/api-reference/audio/createTranscription) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service. """ turn_detection: Optional[RealtimeAudioInputTurnDetection] = None """Configuration for turn detection, ether Server VAD or Semantic VAD. This can be set to `null` to turn off, in which case the client must manually trigger model response. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. Semantic VAD is more advanced and uses a turn detection model (in conjunction with VAD) to semantically estimate whether the user has finished speaking, then dynamically sets a timeout based on this probability. For example, if user audio trails off with "uhhm", the model will score a low probability of turn end and wait longer for the user to continue speaking. This can be useful for more natural conversations, but may have a higher latency. """ ================================================ FILE: src/openai/types/realtime/realtime_audio_config_input_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import TypedDict from .noise_reduction_type import NoiseReductionType from .audio_transcription_param import AudioTranscriptionParam from .realtime_audio_formats_param import RealtimeAudioFormatsParam from .realtime_audio_input_turn_detection_param import RealtimeAudioInputTurnDetectionParam __all__ = ["RealtimeAudioConfigInputParam", "NoiseReduction"] class NoiseReduction(TypedDict, total=False): """Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. """ type: NoiseReductionType """Type of noise reduction. `near_field` is for close-talking microphones such as headphones, `far_field` is for far-field microphones such as laptop or conference room microphones. """ class RealtimeAudioConfigInputParam(TypedDict, total=False): format: RealtimeAudioFormatsParam """The format of the input audio.""" noise_reduction: NoiseReduction """Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. """ transcription: AudioTranscriptionParam """ Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](https://platform.openai.com/docs/api-reference/audio/createTranscription) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service. """ turn_detection: Optional[RealtimeAudioInputTurnDetectionParam] """Configuration for turn detection, ether Server VAD or Semantic VAD. This can be set to `null` to turn off, in which case the client must manually trigger model response. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. Semantic VAD is more advanced and uses a turn detection model (in conjunction with VAD) to semantically estimate whether the user has finished speaking, then dynamically sets a timeout based on this probability. For example, if user audio trails off with "uhhm", the model will score a low probability of turn end and wait longer for the user to continue speaking. This can be useful for more natural conversations, but may have a higher latency. """ ================================================ FILE: src/openai/types/realtime/realtime_audio_config_output.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import Literal, TypeAlias from ..._models import BaseModel from .realtime_audio_formats import RealtimeAudioFormats __all__ = ["RealtimeAudioConfigOutput", "Voice", "VoiceID"] class VoiceID(BaseModel): """Custom voice reference.""" id: str """The custom voice ID, e.g. `voice_1234`.""" Voice: TypeAlias = Union[ str, Literal["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse", "marin", "cedar"], VoiceID ] class RealtimeAudioConfigOutput(BaseModel): format: Optional[RealtimeAudioFormats] = None """The format of the output audio.""" speed: Optional[float] = None """ The speed of the model's spoken response as a multiple of the original speed. 1.0 is the default speed. 0.25 is the minimum speed. 1.5 is the maximum speed. This value can only be changed in between model turns, not while a response is in progress. This parameter is a post-processing adjustment to the audio after it is generated, it's also possible to prompt the model to speak faster or slower. """ voice: Optional[Voice] = None """The voice the model uses to respond. Supported built-in voices are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, `verse`, `marin`, and `cedar`. You may also provide a custom voice object with an `id`, for example `{ "id": "voice_1234" }`. Voice cannot be changed during the session once the model has responded with audio at least once. We recommend `marin` and `cedar` for best quality. """ ================================================ FILE: src/openai/types/realtime/realtime_audio_config_output_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, Required, TypeAlias, TypedDict from .realtime_audio_formats_param import RealtimeAudioFormatsParam __all__ = ["RealtimeAudioConfigOutputParam", "Voice", "VoiceID"] class VoiceID(TypedDict, total=False): """Custom voice reference.""" id: Required[str] """The custom voice ID, e.g. `voice_1234`.""" Voice: TypeAlias = Union[ str, Literal["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse", "marin", "cedar"], VoiceID ] class RealtimeAudioConfigOutputParam(TypedDict, total=False): format: RealtimeAudioFormatsParam """The format of the output audio.""" speed: float """ The speed of the model's spoken response as a multiple of the original speed. 1.0 is the default speed. 0.25 is the minimum speed. 1.5 is the maximum speed. This value can only be changed in between model turns, not while a response is in progress. This parameter is a post-processing adjustment to the audio after it is generated, it's also possible to prompt the model to speak faster or slower. """ voice: Voice """The voice the model uses to respond. Supported built-in voices are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, `verse`, `marin`, and `cedar`. You may also provide a custom voice object with an `id`, for example `{ "id": "voice_1234" }`. Voice cannot be changed during the session once the model has responded with audio at least once. We recommend `marin` and `cedar` for best quality. """ ================================================ FILE: src/openai/types/realtime/realtime_audio_config_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import TypedDict from .realtime_audio_config_input_param import RealtimeAudioConfigInputParam from .realtime_audio_config_output_param import RealtimeAudioConfigOutputParam __all__ = ["RealtimeAudioConfigParam"] class RealtimeAudioConfigParam(TypedDict, total=False): """Configuration for input and output audio.""" input: RealtimeAudioConfigInputParam output: RealtimeAudioConfigOutputParam ================================================ FILE: src/openai/types/realtime/realtime_audio_formats.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = ["RealtimeAudioFormats", "AudioPCM", "AudioPCMU", "AudioPCMA"] class AudioPCM(BaseModel): """The PCM audio format. Only a 24kHz sample rate is supported.""" rate: Optional[Literal[24000]] = None """The sample rate of the audio. Always `24000`.""" type: Optional[Literal["audio/pcm"]] = None """The audio format. Always `audio/pcm`.""" class AudioPCMU(BaseModel): """The G.711 μ-law format.""" type: Optional[Literal["audio/pcmu"]] = None """The audio format. Always `audio/pcmu`.""" class AudioPCMA(BaseModel): """The G.711 A-law format.""" type: Optional[Literal["audio/pcma"]] = None """The audio format. Always `audio/pcma`.""" RealtimeAudioFormats: TypeAlias = Annotated[Union[AudioPCM, AudioPCMU, AudioPCMA], PropertyInfo(discriminator="type")] ================================================ FILE: src/openai/types/realtime/realtime_audio_formats_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, TypeAlias, TypedDict __all__ = ["RealtimeAudioFormatsParam", "AudioPCM", "AudioPCMU", "AudioPCMA"] class AudioPCM(TypedDict, total=False): """The PCM audio format. Only a 24kHz sample rate is supported.""" rate: Literal[24000] """The sample rate of the audio. Always `24000`.""" type: Literal["audio/pcm"] """The audio format. Always `audio/pcm`.""" class AudioPCMU(TypedDict, total=False): """The G.711 μ-law format.""" type: Literal["audio/pcmu"] """The audio format. Always `audio/pcmu`.""" class AudioPCMA(TypedDict, total=False): """The G.711 A-law format.""" type: Literal["audio/pcma"] """The audio format. Always `audio/pcma`.""" RealtimeAudioFormatsParam: TypeAlias = Union[AudioPCM, AudioPCMU, AudioPCMA] ================================================ FILE: src/openai/types/realtime/realtime_audio_input_turn_detection.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = ["RealtimeAudioInputTurnDetection", "ServerVad", "SemanticVad"] class ServerVad(BaseModel): """ Server-side voice activity detection (VAD) which flips on when user speech is detected and off after a period of silence. """ type: Literal["server_vad"] """Type of turn detection, `server_vad` to turn on simple Server VAD.""" create_response: Optional[bool] = None """Whether or not to automatically generate a response when a VAD stop event occurs. If `interrupt_response` is set to `false` this may fail to create a response if the model is already responding. If both `create_response` and `interrupt_response` are set to `false`, the model will never respond automatically but VAD events will still be emitted. """ idle_timeout_ms: Optional[int] = None """Optional timeout after which a model response will be triggered automatically. This is useful for situations in which a long pause from the user is unexpected, such as a phone call. The model will effectively prompt the user to continue the conversation based on the current context. The timeout value will be applied after the last model response's audio has finished playing, i.e. it's set to the `response.done` time plus audio playback duration. An `input_audio_buffer.timeout_triggered` event (plus events associated with the Response) will be emitted when the timeout is reached. Idle timeout is currently only supported for `server_vad` mode. """ interrupt_response: Optional[bool] = None """ Whether or not to automatically interrupt (cancel) any ongoing response with output to the default conversation (i.e. `conversation` of `auto`) when a VAD start event occurs. If `true` then the response will be cancelled, otherwise it will continue until complete. If both `create_response` and `interrupt_response` are set to `false`, the model will never respond automatically but VAD events will still be emitted. """ prefix_padding_ms: Optional[int] = None """Used only for `server_vad` mode. Amount of audio to include before the VAD detected speech (in milliseconds). Defaults to 300ms. """ silence_duration_ms: Optional[int] = None """Used only for `server_vad` mode. Duration of silence to detect speech stop (in milliseconds). Defaults to 500ms. With shorter values the model will respond more quickly, but may jump in on short pauses from the user. """ threshold: Optional[float] = None """Used only for `server_vad` mode. Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A higher threshold will require louder audio to activate the model, and thus might perform better in noisy environments. """ class SemanticVad(BaseModel): """ Server-side semantic turn detection which uses a model to determine when the user has finished speaking. """ type: Literal["semantic_vad"] """Type of turn detection, `semantic_vad` to turn on Semantic VAD.""" create_response: Optional[bool] = None """ Whether or not to automatically generate a response when a VAD stop event occurs. """ eagerness: Optional[Literal["low", "medium", "high", "auto"]] = None """Used only for `semantic_vad` mode. The eagerness of the model to respond. `low` will wait longer for the user to continue speaking, `high` will respond more quickly. `auto` is the default and is equivalent to `medium`. `low`, `medium`, and `high` have max timeouts of 8s, 4s, and 2s respectively. """ interrupt_response: Optional[bool] = None """ Whether or not to automatically interrupt any ongoing response with output to the default conversation (i.e. `conversation` of `auto`) when a VAD start event occurs. """ RealtimeAudioInputTurnDetection: TypeAlias = Annotated[ Union[ServerVad, SemanticVad, None], PropertyInfo(discriminator="type") ] ================================================ FILE: src/openai/types/realtime/realtime_audio_input_turn_detection_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict __all__ = ["RealtimeAudioInputTurnDetectionParam", "ServerVad", "SemanticVad"] class ServerVad(TypedDict, total=False): """ Server-side voice activity detection (VAD) which flips on when user speech is detected and off after a period of silence. """ type: Required[Literal["server_vad"]] """Type of turn detection, `server_vad` to turn on simple Server VAD.""" create_response: bool """Whether or not to automatically generate a response when a VAD stop event occurs. If `interrupt_response` is set to `false` this may fail to create a response if the model is already responding. If both `create_response` and `interrupt_response` are set to `false`, the model will never respond automatically but VAD events will still be emitted. """ idle_timeout_ms: Optional[int] """Optional timeout after which a model response will be triggered automatically. This is useful for situations in which a long pause from the user is unexpected, such as a phone call. The model will effectively prompt the user to continue the conversation based on the current context. The timeout value will be applied after the last model response's audio has finished playing, i.e. it's set to the `response.done` time plus audio playback duration. An `input_audio_buffer.timeout_triggered` event (plus events associated with the Response) will be emitted when the timeout is reached. Idle timeout is currently only supported for `server_vad` mode. """ interrupt_response: bool """ Whether or not to automatically interrupt (cancel) any ongoing response with output to the default conversation (i.e. `conversation` of `auto`) when a VAD start event occurs. If `true` then the response will be cancelled, otherwise it will continue until complete. If both `create_response` and `interrupt_response` are set to `false`, the model will never respond automatically but VAD events will still be emitted. """ prefix_padding_ms: int """Used only for `server_vad` mode. Amount of audio to include before the VAD detected speech (in milliseconds). Defaults to 300ms. """ silence_duration_ms: int """Used only for `server_vad` mode. Duration of silence to detect speech stop (in milliseconds). Defaults to 500ms. With shorter values the model will respond more quickly, but may jump in on short pauses from the user. """ threshold: float """Used only for `server_vad` mode. Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A higher threshold will require louder audio to activate the model, and thus might perform better in noisy environments. """ class SemanticVad(TypedDict, total=False): """ Server-side semantic turn detection which uses a model to determine when the user has finished speaking. """ type: Required[Literal["semantic_vad"]] """Type of turn detection, `semantic_vad` to turn on Semantic VAD.""" create_response: bool """ Whether or not to automatically generate a response when a VAD stop event occurs. """ eagerness: Literal["low", "medium", "high", "auto"] """Used only for `semantic_vad` mode. The eagerness of the model to respond. `low` will wait longer for the user to continue speaking, `high` will respond more quickly. `auto` is the default and is equivalent to `medium`. `low`, `medium`, and `high` have max timeouts of 8s, 4s, and 2s respectively. """ interrupt_response: bool """ Whether or not to automatically interrupt any ongoing response with output to the default conversation (i.e. `conversation` of `auto`) when a VAD start event occurs. """ RealtimeAudioInputTurnDetectionParam: TypeAlias = Union[ServerVad, SemanticVad] ================================================ FILE: src/openai/types/realtime/realtime_client_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from ..._utils import PropertyInfo from .session_update_event import SessionUpdateEvent from .response_cancel_event import ResponseCancelEvent from .response_create_event import ResponseCreateEvent from .conversation_item_create_event import ConversationItemCreateEvent from .conversation_item_delete_event import ConversationItemDeleteEvent from .input_audio_buffer_clear_event import InputAudioBufferClearEvent from .input_audio_buffer_append_event import InputAudioBufferAppendEvent from .input_audio_buffer_commit_event import InputAudioBufferCommitEvent from .output_audio_buffer_clear_event import OutputAudioBufferClearEvent from .conversation_item_retrieve_event import ConversationItemRetrieveEvent from .conversation_item_truncate_event import ConversationItemTruncateEvent __all__ = ["RealtimeClientEvent"] RealtimeClientEvent: TypeAlias = Annotated[ Union[ ConversationItemCreateEvent, ConversationItemDeleteEvent, ConversationItemRetrieveEvent, ConversationItemTruncateEvent, InputAudioBufferAppendEvent, InputAudioBufferClearEvent, OutputAudioBufferClearEvent, InputAudioBufferCommitEvent, ResponseCancelEvent, ResponseCreateEvent, SessionUpdateEvent, ], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/types/realtime/realtime_client_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import TypeAlias from .session_update_event_param import SessionUpdateEventParam from .response_cancel_event_param import ResponseCancelEventParam from .response_create_event_param import ResponseCreateEventParam from .conversation_item_create_event_param import ConversationItemCreateEventParam from .conversation_item_delete_event_param import ConversationItemDeleteEventParam from .input_audio_buffer_clear_event_param import InputAudioBufferClearEventParam from .input_audio_buffer_append_event_param import InputAudioBufferAppendEventParam from .input_audio_buffer_commit_event_param import InputAudioBufferCommitEventParam from .output_audio_buffer_clear_event_param import OutputAudioBufferClearEventParam from .conversation_item_retrieve_event_param import ConversationItemRetrieveEventParam from .conversation_item_truncate_event_param import ConversationItemTruncateEventParam __all__ = ["RealtimeClientEventParam"] RealtimeClientEventParam: TypeAlias = Union[ ConversationItemCreateEventParam, ConversationItemDeleteEventParam, ConversationItemRetrieveEventParam, ConversationItemTruncateEventParam, InputAudioBufferAppendEventParam, InputAudioBufferClearEventParam, OutputAudioBufferClearEventParam, InputAudioBufferCommitEventParam, ResponseCancelEventParam, ResponseCreateEventParam, SessionUpdateEventParam, ] ================================================ FILE: src/openai/types/realtime/realtime_connect_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import TypedDict __all__ = ["RealtimeConnectParams"] class RealtimeConnectParams(TypedDict, total=False): call_id: str model: str ================================================ FILE: src/openai/types/realtime/realtime_conversation_item_assistant_message.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["RealtimeConversationItemAssistantMessage", "Content"] class Content(BaseModel): audio: Optional[str] = None """ Base64-encoded audio bytes, these will be parsed as the format specified in the session output audio type configuration. This defaults to PCM 16-bit 24kHz mono if not specified. """ text: Optional[str] = None """The text content.""" transcript: Optional[str] = None """ The transcript of the audio content, this will always be present if the output type is `audio`. """ type: Optional[Literal["output_text", "output_audio"]] = None """ The content type, `output_text` or `output_audio` depending on the session `output_modalities` configuration. """ class RealtimeConversationItemAssistantMessage(BaseModel): """An assistant message item in a Realtime conversation.""" content: List[Content] """The content of the message.""" role: Literal["assistant"] """The role of the message sender. Always `assistant`.""" type: Literal["message"] """The type of the item. Always `message`.""" id: Optional[str] = None """The unique ID of the item. This may be provided by the client or generated by the server. """ object: Optional[Literal["realtime.item"]] = None """Identifier for the API object being returned - always `realtime.item`. Optional when creating a new item. """ status: Optional[Literal["completed", "incomplete", "in_progress"]] = None """The status of the item. Has no effect on the conversation.""" ================================================ FILE: src/openai/types/realtime/realtime_conversation_item_assistant_message_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Iterable from typing_extensions import Literal, Required, TypedDict __all__ = ["RealtimeConversationItemAssistantMessageParam", "Content"] class Content(TypedDict, total=False): audio: str """ Base64-encoded audio bytes, these will be parsed as the format specified in the session output audio type configuration. This defaults to PCM 16-bit 24kHz mono if not specified. """ text: str """The text content.""" transcript: str """ The transcript of the audio content, this will always be present if the output type is `audio`. """ type: Literal["output_text", "output_audio"] """ The content type, `output_text` or `output_audio` depending on the session `output_modalities` configuration. """ class RealtimeConversationItemAssistantMessageParam(TypedDict, total=False): """An assistant message item in a Realtime conversation.""" content: Required[Iterable[Content]] """The content of the message.""" role: Required[Literal["assistant"]] """The role of the message sender. Always `assistant`.""" type: Required[Literal["message"]] """The type of the item. Always `message`.""" id: str """The unique ID of the item. This may be provided by the client or generated by the server. """ object: Literal["realtime.item"] """Identifier for the API object being returned - always `realtime.item`. Optional when creating a new item. """ status: Literal["completed", "incomplete", "in_progress"] """The status of the item. Has no effect on the conversation.""" ================================================ FILE: src/openai/types/realtime/realtime_conversation_item_function_call.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["RealtimeConversationItemFunctionCall"] class RealtimeConversationItemFunctionCall(BaseModel): """A function call item in a Realtime conversation.""" arguments: str """The arguments of the function call. This is a JSON-encoded string representing the arguments passed to the function, for example `{"arg1": "value1", "arg2": 42}`. """ name: str """The name of the function being called.""" type: Literal["function_call"] """The type of the item. Always `function_call`.""" id: Optional[str] = None """The unique ID of the item. This may be provided by the client or generated by the server. """ call_id: Optional[str] = None """The ID of the function call.""" object: Optional[Literal["realtime.item"]] = None """Identifier for the API object being returned - always `realtime.item`. Optional when creating a new item. """ status: Optional[Literal["completed", "incomplete", "in_progress"]] = None """The status of the item. Has no effect on the conversation.""" ================================================ FILE: src/openai/types/realtime/realtime_conversation_item_function_call_output.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["RealtimeConversationItemFunctionCallOutput"] class RealtimeConversationItemFunctionCallOutput(BaseModel): """A function call output item in a Realtime conversation.""" call_id: str """The ID of the function call this output is for.""" output: str """ The output of the function call, this is free text and can contain any information or simply be empty. """ type: Literal["function_call_output"] """The type of the item. Always `function_call_output`.""" id: Optional[str] = None """The unique ID of the item. This may be provided by the client or generated by the server. """ object: Optional[Literal["realtime.item"]] = None """Identifier for the API object being returned - always `realtime.item`. Optional when creating a new item. """ status: Optional[Literal["completed", "incomplete", "in_progress"]] = None """The status of the item. Has no effect on the conversation.""" ================================================ FILE: src/openai/types/realtime/realtime_conversation_item_function_call_output_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["RealtimeConversationItemFunctionCallOutputParam"] class RealtimeConversationItemFunctionCallOutputParam(TypedDict, total=False): """A function call output item in a Realtime conversation.""" call_id: Required[str] """The ID of the function call this output is for.""" output: Required[str] """ The output of the function call, this is free text and can contain any information or simply be empty. """ type: Required[Literal["function_call_output"]] """The type of the item. Always `function_call_output`.""" id: str """The unique ID of the item. This may be provided by the client or generated by the server. """ object: Literal["realtime.item"] """Identifier for the API object being returned - always `realtime.item`. Optional when creating a new item. """ status: Literal["completed", "incomplete", "in_progress"] """The status of the item. Has no effect on the conversation.""" ================================================ FILE: src/openai/types/realtime/realtime_conversation_item_function_call_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["RealtimeConversationItemFunctionCallParam"] class RealtimeConversationItemFunctionCallParam(TypedDict, total=False): """A function call item in a Realtime conversation.""" arguments: Required[str] """The arguments of the function call. This is a JSON-encoded string representing the arguments passed to the function, for example `{"arg1": "value1", "arg2": 42}`. """ name: Required[str] """The name of the function being called.""" type: Required[Literal["function_call"]] """The type of the item. Always `function_call`.""" id: str """The unique ID of the item. This may be provided by the client or generated by the server. """ call_id: str """The ID of the function call.""" object: Literal["realtime.item"] """Identifier for the API object being returned - always `realtime.item`. Optional when creating a new item. """ status: Literal["completed", "incomplete", "in_progress"] """The status of the item. Has no effect on the conversation.""" ================================================ FILE: src/openai/types/realtime/realtime_conversation_item_system_message.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["RealtimeConversationItemSystemMessage", "Content"] class Content(BaseModel): text: Optional[str] = None """The text content.""" type: Optional[Literal["input_text"]] = None """The content type. Always `input_text` for system messages.""" class RealtimeConversationItemSystemMessage(BaseModel): """ A system message in a Realtime conversation can be used to provide additional context or instructions to the model. This is similar but distinct from the instruction prompt provided at the start of a conversation, as system messages can be added at any point in the conversation. For major changes to the conversation's behavior, use instructions, but for smaller updates (e.g. "the user is now asking about a different topic"), use system messages. """ content: List[Content] """The content of the message.""" role: Literal["system"] """The role of the message sender. Always `system`.""" type: Literal["message"] """The type of the item. Always `message`.""" id: Optional[str] = None """The unique ID of the item. This may be provided by the client or generated by the server. """ object: Optional[Literal["realtime.item"]] = None """Identifier for the API object being returned - always `realtime.item`. Optional when creating a new item. """ status: Optional[Literal["completed", "incomplete", "in_progress"]] = None """The status of the item. Has no effect on the conversation.""" ================================================ FILE: src/openai/types/realtime/realtime_conversation_item_system_message_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Iterable from typing_extensions import Literal, Required, TypedDict __all__ = ["RealtimeConversationItemSystemMessageParam", "Content"] class Content(TypedDict, total=False): text: str """The text content.""" type: Literal["input_text"] """The content type. Always `input_text` for system messages.""" class RealtimeConversationItemSystemMessageParam(TypedDict, total=False): """ A system message in a Realtime conversation can be used to provide additional context or instructions to the model. This is similar but distinct from the instruction prompt provided at the start of a conversation, as system messages can be added at any point in the conversation. For major changes to the conversation's behavior, use instructions, but for smaller updates (e.g. "the user is now asking about a different topic"), use system messages. """ content: Required[Iterable[Content]] """The content of the message.""" role: Required[Literal["system"]] """The role of the message sender. Always `system`.""" type: Required[Literal["message"]] """The type of the item. Always `message`.""" id: str """The unique ID of the item. This may be provided by the client or generated by the server. """ object: Literal["realtime.item"] """Identifier for the API object being returned - always `realtime.item`. Optional when creating a new item. """ status: Literal["completed", "incomplete", "in_progress"] """The status of the item. Has no effect on the conversation.""" ================================================ FILE: src/openai/types/realtime/realtime_conversation_item_user_message.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["RealtimeConversationItemUserMessage", "Content"] class Content(BaseModel): audio: Optional[str] = None """ Base64-encoded audio bytes (for `input_audio`), these will be parsed as the format specified in the session input audio type configuration. This defaults to PCM 16-bit 24kHz mono if not specified. """ detail: Optional[Literal["auto", "low", "high"]] = None """The detail level of the image (for `input_image`). `auto` will default to `high`. """ image_url: Optional[str] = None """Base64-encoded image bytes (for `input_image`) as a data URI. For example `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...`. Supported formats are PNG and JPEG. """ text: Optional[str] = None """The text content (for `input_text`).""" transcript: Optional[str] = None """Transcript of the audio (for `input_audio`). This is not sent to the model, but will be attached to the message item for reference. """ type: Optional[Literal["input_text", "input_audio", "input_image"]] = None """The content type (`input_text`, `input_audio`, or `input_image`).""" class RealtimeConversationItemUserMessage(BaseModel): """A user message item in a Realtime conversation.""" content: List[Content] """The content of the message.""" role: Literal["user"] """The role of the message sender. Always `user`.""" type: Literal["message"] """The type of the item. Always `message`.""" id: Optional[str] = None """The unique ID of the item. This may be provided by the client or generated by the server. """ object: Optional[Literal["realtime.item"]] = None """Identifier for the API object being returned - always `realtime.item`. Optional when creating a new item. """ status: Optional[Literal["completed", "incomplete", "in_progress"]] = None """The status of the item. Has no effect on the conversation.""" ================================================ FILE: src/openai/types/realtime/realtime_conversation_item_user_message_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Iterable from typing_extensions import Literal, Required, TypedDict __all__ = ["RealtimeConversationItemUserMessageParam", "Content"] class Content(TypedDict, total=False): audio: str """ Base64-encoded audio bytes (for `input_audio`), these will be parsed as the format specified in the session input audio type configuration. This defaults to PCM 16-bit 24kHz mono if not specified. """ detail: Literal["auto", "low", "high"] """The detail level of the image (for `input_image`). `auto` will default to `high`. """ image_url: str """Base64-encoded image bytes (for `input_image`) as a data URI. For example `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...`. Supported formats are PNG and JPEG. """ text: str """The text content (for `input_text`).""" transcript: str """Transcript of the audio (for `input_audio`). This is not sent to the model, but will be attached to the message item for reference. """ type: Literal["input_text", "input_audio", "input_image"] """The content type (`input_text`, `input_audio`, or `input_image`).""" class RealtimeConversationItemUserMessageParam(TypedDict, total=False): """A user message item in a Realtime conversation.""" content: Required[Iterable[Content]] """The content of the message.""" role: Required[Literal["user"]] """The role of the message sender. Always `user`.""" type: Required[Literal["message"]] """The type of the item. Always `message`.""" id: str """The unique ID of the item. This may be provided by the client or generated by the server. """ object: Literal["realtime.item"] """Identifier for the API object being returned - always `realtime.item`. Optional when creating a new item. """ status: Literal["completed", "incomplete", "in_progress"] """The status of the item. Has no effect on the conversation.""" ================================================ FILE: src/openai/types/realtime/realtime_error.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from ..._models import BaseModel __all__ = ["RealtimeError"] class RealtimeError(BaseModel): """Details of the error.""" message: str """A human-readable error message.""" type: str """The type of error (e.g., "invalid_request_error", "server_error").""" code: Optional[str] = None """Error code, if any.""" event_id: Optional[str] = None """The event_id of the client event that caused the error, if applicable.""" param: Optional[str] = None """Parameter related to the error, if any.""" ================================================ FILE: src/openai/types/realtime/realtime_error_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel from .realtime_error import RealtimeError __all__ = ["RealtimeErrorEvent"] class RealtimeErrorEvent(BaseModel): """ Returned when an error occurs, which could be a client problem or a server problem. Most errors are recoverable and the session will stay open, we recommend to implementors to monitor and log error messages by default. """ error: RealtimeError """Details of the error.""" event_id: str """The unique ID of the server event.""" type: Literal["error"] """The event type, must be `error`.""" ================================================ FILE: src/openai/types/realtime/realtime_function_tool.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["RealtimeFunctionTool"] class RealtimeFunctionTool(BaseModel): description: Optional[str] = None """ The description of the function, including guidance on when and how to call it, and guidance about what to tell the user when calling (if anything). """ name: Optional[str] = None """The name of the function.""" parameters: Optional[object] = None """Parameters of the function in JSON Schema.""" type: Optional[Literal["function"]] = None """The type of the tool, i.e. `function`.""" ================================================ FILE: src/openai/types/realtime/realtime_function_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["RealtimeFunctionToolParam"] class RealtimeFunctionToolParam(TypedDict, total=False): description: str """ The description of the function, including guidance on when and how to call it, and guidance about what to tell the user when calling (if anything). """ name: str """The name of the function.""" parameters: object """Parameters of the function in JSON Schema.""" type: Literal["function"] """The type of the tool, i.e. `function`.""" ================================================ FILE: src/openai/types/realtime/realtime_mcp_approval_request.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["RealtimeMcpApprovalRequest"] class RealtimeMcpApprovalRequest(BaseModel): """A Realtime item requesting human approval of a tool invocation.""" id: str """The unique ID of the approval request.""" arguments: str """A JSON string of arguments for the tool.""" name: str """The name of the tool to run.""" server_label: str """The label of the MCP server making the request.""" type: Literal["mcp_approval_request"] """The type of the item. Always `mcp_approval_request`.""" ================================================ FILE: src/openai/types/realtime/realtime_mcp_approval_request_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["RealtimeMcpApprovalRequestParam"] class RealtimeMcpApprovalRequestParam(TypedDict, total=False): """A Realtime item requesting human approval of a tool invocation.""" id: Required[str] """The unique ID of the approval request.""" arguments: Required[str] """A JSON string of arguments for the tool.""" name: Required[str] """The name of the tool to run.""" server_label: Required[str] """The label of the MCP server making the request.""" type: Required[Literal["mcp_approval_request"]] """The type of the item. Always `mcp_approval_request`.""" ================================================ FILE: src/openai/types/realtime/realtime_mcp_approval_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["RealtimeMcpApprovalResponse"] class RealtimeMcpApprovalResponse(BaseModel): """A Realtime item responding to an MCP approval request.""" id: str """The unique ID of the approval response.""" approval_request_id: str """The ID of the approval request being answered.""" approve: bool """Whether the request was approved.""" type: Literal["mcp_approval_response"] """The type of the item. Always `mcp_approval_response`.""" reason: Optional[str] = None """Optional reason for the decision.""" ================================================ FILE: src/openai/types/realtime/realtime_mcp_approval_response_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Literal, Required, TypedDict __all__ = ["RealtimeMcpApprovalResponseParam"] class RealtimeMcpApprovalResponseParam(TypedDict, total=False): """A Realtime item responding to an MCP approval request.""" id: Required[str] """The unique ID of the approval response.""" approval_request_id: Required[str] """The ID of the approval request being answered.""" approve: Required[bool] """Whether the request was approved.""" type: Required[Literal["mcp_approval_response"]] """The type of the item. Always `mcp_approval_response`.""" reason: Optional[str] """Optional reason for the decision.""" ================================================ FILE: src/openai/types/realtime/realtime_mcp_list_tools.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["RealtimeMcpListTools", "Tool"] class Tool(BaseModel): """A tool available on an MCP server.""" input_schema: object """The JSON schema describing the tool's input.""" name: str """The name of the tool.""" annotations: Optional[object] = None """Additional annotations about the tool.""" description: Optional[str] = None """The description of the tool.""" class RealtimeMcpListTools(BaseModel): """A Realtime item listing tools available on an MCP server.""" server_label: str """The label of the MCP server.""" tools: List[Tool] """The tools available on the server.""" type: Literal["mcp_list_tools"] """The type of the item. Always `mcp_list_tools`.""" id: Optional[str] = None """The unique ID of the list.""" ================================================ FILE: src/openai/types/realtime/realtime_mcp_list_tools_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Iterable, Optional from typing_extensions import Literal, Required, TypedDict __all__ = ["RealtimeMcpListToolsParam", "Tool"] class Tool(TypedDict, total=False): """A tool available on an MCP server.""" input_schema: Required[object] """The JSON schema describing the tool's input.""" name: Required[str] """The name of the tool.""" annotations: Optional[object] """Additional annotations about the tool.""" description: Optional[str] """The description of the tool.""" class RealtimeMcpListToolsParam(TypedDict, total=False): """A Realtime item listing tools available on an MCP server.""" server_label: Required[str] """The label of the MCP server.""" tools: Required[Iterable[Tool]] """The tools available on the server.""" type: Required[Literal["mcp_list_tools"]] """The type of the item. Always `mcp_list_tools`.""" id: str """The unique ID of the list.""" ================================================ FILE: src/openai/types/realtime/realtime_mcp_protocol_error.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["RealtimeMcpProtocolError"] class RealtimeMcpProtocolError(BaseModel): code: int message: str type: Literal["protocol_error"] ================================================ FILE: src/openai/types/realtime/realtime_mcp_protocol_error_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["RealtimeMcpProtocolErrorParam"] class RealtimeMcpProtocolErrorParam(TypedDict, total=False): code: Required[int] message: Required[str] type: Required[Literal["protocol_error"]] ================================================ FILE: src/openai/types/realtime/realtime_mcp_tool_call.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .realtime_mcphttp_error import RealtimeMcphttpError from .realtime_mcp_protocol_error import RealtimeMcpProtocolError from .realtime_mcp_tool_execution_error import RealtimeMcpToolExecutionError __all__ = ["RealtimeMcpToolCall", "Error"] Error: TypeAlias = Annotated[ Union[RealtimeMcpProtocolError, RealtimeMcpToolExecutionError, RealtimeMcphttpError, None], PropertyInfo(discriminator="type"), ] class RealtimeMcpToolCall(BaseModel): """A Realtime item representing an invocation of a tool on an MCP server.""" id: str """The unique ID of the tool call.""" arguments: str """A JSON string of the arguments passed to the tool.""" name: str """The name of the tool that was run.""" server_label: str """The label of the MCP server running the tool.""" type: Literal["mcp_call"] """The type of the item. Always `mcp_call`.""" approval_request_id: Optional[str] = None """The ID of an associated approval request, if any.""" error: Optional[Error] = None """The error from the tool call, if any.""" output: Optional[str] = None """The output from the tool call.""" ================================================ FILE: src/openai/types/realtime/realtime_mcp_tool_call_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from .realtime_mcphttp_error_param import RealtimeMcphttpErrorParam from .realtime_mcp_protocol_error_param import RealtimeMcpProtocolErrorParam from .realtime_mcp_tool_execution_error_param import RealtimeMcpToolExecutionErrorParam __all__ = ["RealtimeMcpToolCallParam", "Error"] Error: TypeAlias = Union[RealtimeMcpProtocolErrorParam, RealtimeMcpToolExecutionErrorParam, RealtimeMcphttpErrorParam] class RealtimeMcpToolCallParam(TypedDict, total=False): """A Realtime item representing an invocation of a tool on an MCP server.""" id: Required[str] """The unique ID of the tool call.""" arguments: Required[str] """A JSON string of the arguments passed to the tool.""" name: Required[str] """The name of the tool that was run.""" server_label: Required[str] """The label of the MCP server running the tool.""" type: Required[Literal["mcp_call"]] """The type of the item. Always `mcp_call`.""" approval_request_id: Optional[str] """The ID of an associated approval request, if any.""" error: Optional[Error] """The error from the tool call, if any.""" output: Optional[str] """The output from the tool call.""" ================================================ FILE: src/openai/types/realtime/realtime_mcp_tool_execution_error.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["RealtimeMcpToolExecutionError"] class RealtimeMcpToolExecutionError(BaseModel): message: str type: Literal["tool_execution_error"] ================================================ FILE: src/openai/types/realtime/realtime_mcp_tool_execution_error_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["RealtimeMcpToolExecutionErrorParam"] class RealtimeMcpToolExecutionErrorParam(TypedDict, total=False): message: Required[str] type: Required[Literal["tool_execution_error"]] ================================================ FILE: src/openai/types/realtime/realtime_mcphttp_error.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["RealtimeMcphttpError"] class RealtimeMcphttpError(BaseModel): code: int message: str type: Literal["http_error"] ================================================ FILE: src/openai/types/realtime/realtime_mcphttp_error_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["RealtimeMcphttpErrorParam"] class RealtimeMcphttpErrorParam(TypedDict, total=False): code: Required[int] message: Required[str] type: Required[Literal["http_error"]] ================================================ FILE: src/openai/types/realtime/realtime_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal from ..._models import BaseModel from ..shared.metadata import Metadata from .conversation_item import ConversationItem from .realtime_audio_formats import RealtimeAudioFormats from .realtime_response_usage import RealtimeResponseUsage from .realtime_response_status import RealtimeResponseStatus __all__ = ["RealtimeResponse", "Audio", "AudioOutput"] class AudioOutput(BaseModel): format: Optional[RealtimeAudioFormats] = None """The format of the output audio.""" voice: Union[ str, Literal["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse", "marin", "cedar"], None ] = None """The voice the model uses to respond. Voice cannot be changed during the session once the model has responded with audio at least once. Current voice options are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, `verse`, `marin`, and `cedar`. We recommend `marin` and `cedar` for best quality. """ class Audio(BaseModel): """Configuration for audio output.""" output: Optional[AudioOutput] = None class RealtimeResponse(BaseModel): """The response resource.""" id: Optional[str] = None """The unique ID of the response, will look like `resp_1234`.""" audio: Optional[Audio] = None """Configuration for audio output.""" conversation_id: Optional[str] = None """ Which conversation the response is added to, determined by the `conversation` field in the `response.create` event. If `auto`, the response will be added to the default conversation and the value of `conversation_id` will be an id like `conv_1234`. If `none`, the response will not be added to any conversation and the value of `conversation_id` will be `null`. If responses are being triggered automatically by VAD the response will be added to the default conversation """ max_output_tokens: Union[int, Literal["inf"], None] = None """ Maximum number of output tokens for a single assistant response, inclusive of tool calls, that was used in this response. """ metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ object: Optional[Literal["realtime.response"]] = None """The object type, must be `realtime.response`.""" output: Optional[List[ConversationItem]] = None """The list of output items generated by the response.""" output_modalities: Optional[List[Literal["text", "audio"]]] = None """ The set of modalities the model used to respond, currently the only possible values are `[\"audio\"]`, `[\"text\"]`. Audio output always include a text transcript. Setting the output to mode `text` will disable audio output from the model. """ status: Optional[Literal["completed", "cancelled", "failed", "incomplete", "in_progress"]] = None """ The final status of the response (`completed`, `cancelled`, `failed`, or `incomplete`, `in_progress`). """ status_details: Optional[RealtimeResponseStatus] = None """Additional details about the status.""" usage: Optional[RealtimeResponseUsage] = None """Usage statistics for the Response, this will correspond to billing. A Realtime API session will maintain a conversation context and append new Items to the Conversation, thus output from previous turns (text and audio tokens) will become the input for later turns. """ ================================================ FILE: src/openai/types/realtime/realtime_response_create_audio_output.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import Literal, TypeAlias from ..._models import BaseModel from .realtime_audio_formats import RealtimeAudioFormats __all__ = ["RealtimeResponseCreateAudioOutput", "Output", "OutputVoice", "OutputVoiceID"] class OutputVoiceID(BaseModel): """Custom voice reference.""" id: str """The custom voice ID, e.g. `voice_1234`.""" OutputVoice: TypeAlias = Union[ str, Literal["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse", "marin", "cedar"], OutputVoiceID ] class Output(BaseModel): format: Optional[RealtimeAudioFormats] = None """The format of the output audio.""" voice: Optional[OutputVoice] = None """The voice the model uses to respond. Supported built-in voices are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, `verse`, `marin`, and `cedar`. You may also provide a custom voice object with an `id`, for example `{ "id": "voice_1234" }`. Voice cannot be changed during the session once the model has responded with audio at least once. We recommend `marin` and `cedar` for best quality. """ class RealtimeResponseCreateAudioOutput(BaseModel): """Configuration for audio input and output.""" output: Optional[Output] = None ================================================ FILE: src/openai/types/realtime/realtime_response_create_audio_output_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, Required, TypeAlias, TypedDict from .realtime_audio_formats_param import RealtimeAudioFormatsParam __all__ = ["RealtimeResponseCreateAudioOutputParam", "Output", "OutputVoice", "OutputVoiceID"] class OutputVoiceID(TypedDict, total=False): """Custom voice reference.""" id: Required[str] """The custom voice ID, e.g. `voice_1234`.""" OutputVoice: TypeAlias = Union[ str, Literal["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse", "marin", "cedar"], OutputVoiceID ] class Output(TypedDict, total=False): format: RealtimeAudioFormatsParam """The format of the output audio.""" voice: OutputVoice """The voice the model uses to respond. Supported built-in voices are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, `verse`, `marin`, and `cedar`. You may also provide a custom voice object with an `id`, for example `{ "id": "voice_1234" }`. Voice cannot be changed during the session once the model has responded with audio at least once. We recommend `marin` and `cedar` for best quality. """ class RealtimeResponseCreateAudioOutputParam(TypedDict, total=False): """Configuration for audio input and output.""" output: Output ================================================ FILE: src/openai/types/realtime/realtime_response_create_mcp_tool.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal, TypeAlias from ..._models import BaseModel __all__ = [ "RealtimeResponseCreateMcpTool", "AllowedTools", "AllowedToolsMcpToolFilter", "RequireApproval", "RequireApprovalMcpToolApprovalFilter", "RequireApprovalMcpToolApprovalFilterAlways", "RequireApprovalMcpToolApprovalFilterNever", ] class AllowedToolsMcpToolFilter(BaseModel): """A filter object to specify which tools are allowed.""" read_only: Optional[bool] = None """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: Optional[List[str]] = None """List of allowed tool names.""" AllowedTools: TypeAlias = Union[List[str], AllowedToolsMcpToolFilter, None] class RequireApprovalMcpToolApprovalFilterAlways(BaseModel): """A filter object to specify which tools are allowed.""" read_only: Optional[bool] = None """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: Optional[List[str]] = None """List of allowed tool names.""" class RequireApprovalMcpToolApprovalFilterNever(BaseModel): """A filter object to specify which tools are allowed.""" read_only: Optional[bool] = None """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: Optional[List[str]] = None """List of allowed tool names.""" class RequireApprovalMcpToolApprovalFilter(BaseModel): """Specify which of the MCP server's tools require approval. Can be `always`, `never`, or a filter object associated with tools that require approval. """ always: Optional[RequireApprovalMcpToolApprovalFilterAlways] = None """A filter object to specify which tools are allowed.""" never: Optional[RequireApprovalMcpToolApprovalFilterNever] = None """A filter object to specify which tools are allowed.""" RequireApproval: TypeAlias = Union[RequireApprovalMcpToolApprovalFilter, Literal["always", "never"], None] class RealtimeResponseCreateMcpTool(BaseModel): """ Give the model access to additional tools via remote Model Context Protocol (MCP) servers. [Learn more about MCP](https://platform.openai.com/docs/guides/tools-remote-mcp). """ server_label: str """A label for this MCP server, used to identify it in tool calls.""" type: Literal["mcp"] """The type of the MCP tool. Always `mcp`.""" allowed_tools: Optional[AllowedTools] = None """List of allowed tool names or a filter object.""" authorization: Optional[str] = None """ An OAuth access token that can be used with a remote MCP server, either with a custom MCP server URL or a service connector. Your application must handle the OAuth authorization flow and provide the token here. """ connector_id: Optional[ Literal[ "connector_dropbox", "connector_gmail", "connector_googlecalendar", "connector_googledrive", "connector_microsoftteams", "connector_outlookcalendar", "connector_outlookemail", "connector_sharepoint", ] ] = None """Identifier for service connectors, like those available in ChatGPT. One of `server_url` or `connector_id` must be provided. Learn more about service connectors [here](https://platform.openai.com/docs/guides/tools-remote-mcp#connectors). Currently supported `connector_id` values are: - Dropbox: `connector_dropbox` - Gmail: `connector_gmail` - Google Calendar: `connector_googlecalendar` - Google Drive: `connector_googledrive` - Microsoft Teams: `connector_microsoftteams` - Outlook Calendar: `connector_outlookcalendar` - Outlook Email: `connector_outlookemail` - SharePoint: `connector_sharepoint` """ defer_loading: Optional[bool] = None """Whether this MCP tool is deferred and discovered via tool search.""" headers: Optional[Dict[str, str]] = None """Optional HTTP headers to send to the MCP server. Use for authentication or other purposes. """ require_approval: Optional[RequireApproval] = None """Specify which of the MCP server's tools require approval.""" server_description: Optional[str] = None """Optional description of the MCP server, used to provide more context.""" server_url: Optional[str] = None """The URL for the MCP server. One of `server_url` or `connector_id` must be provided. """ ================================================ FILE: src/openai/types/realtime/realtime_response_create_mcp_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Union, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import SequenceNotStr __all__ = [ "RealtimeResponseCreateMcpToolParam", "AllowedTools", "AllowedToolsMcpToolFilter", "RequireApproval", "RequireApprovalMcpToolApprovalFilter", "RequireApprovalMcpToolApprovalFilterAlways", "RequireApprovalMcpToolApprovalFilterNever", ] class AllowedToolsMcpToolFilter(TypedDict, total=False): """A filter object to specify which tools are allowed.""" read_only: bool """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: SequenceNotStr[str] """List of allowed tool names.""" AllowedTools: TypeAlias = Union[SequenceNotStr[str], AllowedToolsMcpToolFilter] class RequireApprovalMcpToolApprovalFilterAlways(TypedDict, total=False): """A filter object to specify which tools are allowed.""" read_only: bool """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: SequenceNotStr[str] """List of allowed tool names.""" class RequireApprovalMcpToolApprovalFilterNever(TypedDict, total=False): """A filter object to specify which tools are allowed.""" read_only: bool """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: SequenceNotStr[str] """List of allowed tool names.""" class RequireApprovalMcpToolApprovalFilter(TypedDict, total=False): """Specify which of the MCP server's tools require approval. Can be `always`, `never`, or a filter object associated with tools that require approval. """ always: RequireApprovalMcpToolApprovalFilterAlways """A filter object to specify which tools are allowed.""" never: RequireApprovalMcpToolApprovalFilterNever """A filter object to specify which tools are allowed.""" RequireApproval: TypeAlias = Union[RequireApprovalMcpToolApprovalFilter, Literal["always", "never"]] class RealtimeResponseCreateMcpToolParam(TypedDict, total=False): """ Give the model access to additional tools via remote Model Context Protocol (MCP) servers. [Learn more about MCP](https://platform.openai.com/docs/guides/tools-remote-mcp). """ server_label: Required[str] """A label for this MCP server, used to identify it in tool calls.""" type: Required[Literal["mcp"]] """The type of the MCP tool. Always `mcp`.""" allowed_tools: Optional[AllowedTools] """List of allowed tool names or a filter object.""" authorization: str """ An OAuth access token that can be used with a remote MCP server, either with a custom MCP server URL or a service connector. Your application must handle the OAuth authorization flow and provide the token here. """ connector_id: Literal[ "connector_dropbox", "connector_gmail", "connector_googlecalendar", "connector_googledrive", "connector_microsoftteams", "connector_outlookcalendar", "connector_outlookemail", "connector_sharepoint", ] """Identifier for service connectors, like those available in ChatGPT. One of `server_url` or `connector_id` must be provided. Learn more about service connectors [here](https://platform.openai.com/docs/guides/tools-remote-mcp#connectors). Currently supported `connector_id` values are: - Dropbox: `connector_dropbox` - Gmail: `connector_gmail` - Google Calendar: `connector_googlecalendar` - Google Drive: `connector_googledrive` - Microsoft Teams: `connector_microsoftteams` - Outlook Calendar: `connector_outlookcalendar` - Outlook Email: `connector_outlookemail` - SharePoint: `connector_sharepoint` """ defer_loading: bool """Whether this MCP tool is deferred and discovered via tool search.""" headers: Optional[Dict[str, str]] """Optional HTTP headers to send to the MCP server. Use for authentication or other purposes. """ require_approval: Optional[RequireApproval] """Specify which of the MCP server's tools require approval.""" server_description: str """Optional description of the MCP server, used to provide more context.""" server_url: str """The URL for the MCP server. One of `server_url` or `connector_id` must be provided. """ ================================================ FILE: src/openai/types/realtime/realtime_response_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, TypeAlias from ..._models import BaseModel from ..shared.metadata import Metadata from .conversation_item import ConversationItem from .realtime_function_tool import RealtimeFunctionTool from ..responses.response_prompt import ResponsePrompt from ..responses.tool_choice_mcp import ToolChoiceMcp from ..responses.tool_choice_options import ToolChoiceOptions from ..responses.tool_choice_function import ToolChoiceFunction from .realtime_response_create_mcp_tool import RealtimeResponseCreateMcpTool from .realtime_response_create_audio_output import RealtimeResponseCreateAudioOutput __all__ = ["RealtimeResponseCreateParams", "ToolChoice", "Tool"] ToolChoice: TypeAlias = Union[ToolChoiceOptions, ToolChoiceFunction, ToolChoiceMcp] Tool: TypeAlias = Union[RealtimeFunctionTool, RealtimeResponseCreateMcpTool] class RealtimeResponseCreateParams(BaseModel): """Create a new Realtime response with these parameters""" audio: Optional[RealtimeResponseCreateAudioOutput] = None """Configuration for audio input and output.""" conversation: Union[str, Literal["auto", "none"], None] = None """Controls which conversation the response is added to. Currently supports `auto` and `none`, with `auto` as the default value. The `auto` value means that the contents of the response will be added to the default conversation. Set this to `none` to create an out-of-band response which will not add items to default conversation. """ input: Optional[List[ConversationItem]] = None """Input items to include in the prompt for the model. Using this field creates a new context for this Response instead of using the default conversation. An empty array `[]` will clear the context for this Response. Note that this can include references to items that previously appeared in the session using their id. """ instructions: Optional[str] = None """The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. "be extremely succinct", "act friendly", "here are examples of good responses") and on audio behavior (e.g. "talk quickly", "inject emotion into your voice", "laugh frequently"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior. Note that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session. """ max_output_tokens: Union[int, Literal["inf"], None] = None """ Maximum number of output tokens for a single assistant response, inclusive of tool calls. Provide an integer between 1 and 4096 to limit output tokens, or `inf` for the maximum available tokens for a given model. Defaults to `inf`. """ metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ output_modalities: Optional[List[Literal["text", "audio"]]] = None """ The set of modalities the model used to respond, currently the only possible values are `[\"audio\"]`, `[\"text\"]`. Audio output always include a text transcript. Setting the output to mode `text` will disable audio output from the model. """ prompt: Optional[ResponsePrompt] = None """ Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). """ tool_choice: Optional[ToolChoice] = None """How the model chooses tools. Provide one of the string modes or force a specific function/MCP tool. """ tools: Optional[List[Tool]] = None """Tools available to the model.""" ================================================ FILE: src/openai/types/realtime/realtime_response_create_params_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List, Union, Iterable, Optional from typing_extensions import Literal, TypeAlias, TypedDict from ..shared_params.metadata import Metadata from .conversation_item_param import ConversationItemParam from .realtime_function_tool_param import RealtimeFunctionToolParam from ..responses.tool_choice_options import ToolChoiceOptions from ..responses.response_prompt_param import ResponsePromptParam from ..responses.tool_choice_mcp_param import ToolChoiceMcpParam from ..responses.tool_choice_function_param import ToolChoiceFunctionParam from .realtime_response_create_mcp_tool_param import RealtimeResponseCreateMcpToolParam from .realtime_response_create_audio_output_param import RealtimeResponseCreateAudioOutputParam __all__ = ["RealtimeResponseCreateParamsParam", "ToolChoice", "Tool"] ToolChoice: TypeAlias = Union[ToolChoiceOptions, ToolChoiceFunctionParam, ToolChoiceMcpParam] Tool: TypeAlias = Union[RealtimeFunctionToolParam, RealtimeResponseCreateMcpToolParam] class RealtimeResponseCreateParamsParam(TypedDict, total=False): """Create a new Realtime response with these parameters""" audio: RealtimeResponseCreateAudioOutputParam """Configuration for audio input and output.""" conversation: Union[str, Literal["auto", "none"]] """Controls which conversation the response is added to. Currently supports `auto` and `none`, with `auto` as the default value. The `auto` value means that the contents of the response will be added to the default conversation. Set this to `none` to create an out-of-band response which will not add items to default conversation. """ input: Iterable[ConversationItemParam] """Input items to include in the prompt for the model. Using this field creates a new context for this Response instead of using the default conversation. An empty array `[]` will clear the context for this Response. Note that this can include references to items that previously appeared in the session using their id. """ instructions: str """The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. "be extremely succinct", "act friendly", "here are examples of good responses") and on audio behavior (e.g. "talk quickly", "inject emotion into your voice", "laugh frequently"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior. Note that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session. """ max_output_tokens: Union[int, Literal["inf"]] """ Maximum number of output tokens for a single assistant response, inclusive of tool calls. Provide an integer between 1 and 4096 to limit output tokens, or `inf` for the maximum available tokens for a given model. Defaults to `inf`. """ metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ output_modalities: List[Literal["text", "audio"]] """ The set of modalities the model used to respond, currently the only possible values are `[\"audio\"]`, `[\"text\"]`. Audio output always include a text transcript. Setting the output to mode `text` will disable audio output from the model. """ prompt: Optional[ResponsePromptParam] """ Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). """ tool_choice: ToolChoice """How the model chooses tools. Provide one of the string modes or force a specific function/MCP tool. """ tools: Iterable[Tool] """Tools available to the model.""" ================================================ FILE: src/openai/types/realtime/realtime_response_status.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["RealtimeResponseStatus", "Error"] class Error(BaseModel): """ A description of the error that caused the response to fail, populated when the `status` is `failed`. """ code: Optional[str] = None """Error code, if any.""" type: Optional[str] = None """The type of error.""" class RealtimeResponseStatus(BaseModel): """Additional details about the status.""" error: Optional[Error] = None """ A description of the error that caused the response to fail, populated when the `status` is `failed`. """ reason: Optional[Literal["turn_detected", "client_cancelled", "max_output_tokens", "content_filter"]] = None """The reason the Response did not complete. For a `cancelled` Response, one of `turn_detected` (the server VAD detected a new start of speech) or `client_cancelled` (the client sent a cancel event). For an `incomplete` Response, one of `max_output_tokens` or `content_filter` (the server-side safety filter activated and cut off the response). """ type: Optional[Literal["completed", "cancelled", "incomplete", "failed"]] = None """ The type of error that caused the response to fail, corresponding with the `status` field (`completed`, `cancelled`, `incomplete`, `failed`). """ ================================================ FILE: src/openai/types/realtime/realtime_response_usage.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from ..._models import BaseModel from .realtime_response_usage_input_token_details import RealtimeResponseUsageInputTokenDetails from .realtime_response_usage_output_token_details import RealtimeResponseUsageOutputTokenDetails __all__ = ["RealtimeResponseUsage"] class RealtimeResponseUsage(BaseModel): """Usage statistics for the Response, this will correspond to billing. A Realtime API session will maintain a conversation context and append new Items to the Conversation, thus output from previous turns (text and audio tokens) will become the input for later turns. """ input_token_details: Optional[RealtimeResponseUsageInputTokenDetails] = None """Details about the input tokens used in the Response. Cached tokens are tokens from previous turns in the conversation that are included as context for the current response. Cached tokens here are counted as a subset of input tokens, meaning input tokens will include cached and uncached tokens. """ input_tokens: Optional[int] = None """ The number of input tokens used in the Response, including text and audio tokens. """ output_token_details: Optional[RealtimeResponseUsageOutputTokenDetails] = None """Details about the output tokens used in the Response.""" output_tokens: Optional[int] = None """ The number of output tokens sent in the Response, including text and audio tokens. """ total_tokens: Optional[int] = None """ The total number of tokens in the Response including input and output text and audio tokens. """ ================================================ FILE: src/openai/types/realtime/realtime_response_usage_input_token_details.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from ..._models import BaseModel __all__ = ["RealtimeResponseUsageInputTokenDetails", "CachedTokensDetails"] class CachedTokensDetails(BaseModel): """Details about the cached tokens used as input for the Response.""" audio_tokens: Optional[int] = None """The number of cached audio tokens used as input for the Response.""" image_tokens: Optional[int] = None """The number of cached image tokens used as input for the Response.""" text_tokens: Optional[int] = None """The number of cached text tokens used as input for the Response.""" class RealtimeResponseUsageInputTokenDetails(BaseModel): """Details about the input tokens used in the Response. Cached tokens are tokens from previous turns in the conversation that are included as context for the current response. Cached tokens here are counted as a subset of input tokens, meaning input tokens will include cached and uncached tokens. """ audio_tokens: Optional[int] = None """The number of audio tokens used as input for the Response.""" cached_tokens: Optional[int] = None """The number of cached tokens used as input for the Response.""" cached_tokens_details: Optional[CachedTokensDetails] = None """Details about the cached tokens used as input for the Response.""" image_tokens: Optional[int] = None """The number of image tokens used as input for the Response.""" text_tokens: Optional[int] = None """The number of text tokens used as input for the Response.""" ================================================ FILE: src/openai/types/realtime/realtime_response_usage_output_token_details.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from ..._models import BaseModel __all__ = ["RealtimeResponseUsageOutputTokenDetails"] class RealtimeResponseUsageOutputTokenDetails(BaseModel): """Details about the output tokens used in the Response.""" audio_tokens: Optional[int] = None """The number of audio tokens used in the Response.""" text_tokens: Optional[int] = None """The number of text tokens used in the Response.""" ================================================ FILE: src/openai/types/realtime/realtime_server_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .conversation_item import ConversationItem from .response_done_event import ResponseDoneEvent from .realtime_error_event import RealtimeErrorEvent from .mcp_list_tools_failed import McpListToolsFailed from .session_created_event import SessionCreatedEvent from .session_updated_event import SessionUpdatedEvent from .conversation_item_done import ConversationItemDone from .response_created_event import ResponseCreatedEvent from .conversation_item_added import ConversationItemAdded from .mcp_list_tools_completed import McpListToolsCompleted from .response_mcp_call_failed import ResponseMcpCallFailed from .response_text_done_event import ResponseTextDoneEvent from .rate_limits_updated_event import RateLimitsUpdatedEvent from .response_audio_done_event import ResponseAudioDoneEvent from .response_text_delta_event import ResponseTextDeltaEvent from .conversation_created_event import ConversationCreatedEvent from .mcp_list_tools_in_progress import McpListToolsInProgress from .response_audio_delta_event import ResponseAudioDeltaEvent from .response_mcp_call_completed import ResponseMcpCallCompleted from .response_mcp_call_in_progress import ResponseMcpCallInProgress from .conversation_item_created_event import ConversationItemCreatedEvent from .conversation_item_deleted_event import ConversationItemDeletedEvent from .response_output_item_done_event import ResponseOutputItemDoneEvent from .input_audio_buffer_cleared_event import InputAudioBufferClearedEvent from .response_content_part_done_event import ResponseContentPartDoneEvent from .response_mcp_call_arguments_done import ResponseMcpCallArgumentsDone from .response_output_item_added_event import ResponseOutputItemAddedEvent from .conversation_item_truncated_event import ConversationItemTruncatedEvent from .response_content_part_added_event import ResponseContentPartAddedEvent from .response_mcp_call_arguments_delta import ResponseMcpCallArgumentsDelta from .input_audio_buffer_committed_event import InputAudioBufferCommittedEvent from .input_audio_buffer_timeout_triggered import InputAudioBufferTimeoutTriggered from .response_audio_transcript_done_event import ResponseAudioTranscriptDoneEvent from .response_audio_transcript_delta_event import ResponseAudioTranscriptDeltaEvent from .input_audio_buffer_speech_started_event import InputAudioBufferSpeechStartedEvent from .input_audio_buffer_speech_stopped_event import InputAudioBufferSpeechStoppedEvent from .response_function_call_arguments_done_event import ResponseFunctionCallArgumentsDoneEvent from .input_audio_buffer_dtmf_event_received_event import InputAudioBufferDtmfEventReceivedEvent from .response_function_call_arguments_delta_event import ResponseFunctionCallArgumentsDeltaEvent from .conversation_item_input_audio_transcription_segment import ConversationItemInputAudioTranscriptionSegment from .conversation_item_input_audio_transcription_delta_event import ConversationItemInputAudioTranscriptionDeltaEvent from .conversation_item_input_audio_transcription_failed_event import ConversationItemInputAudioTranscriptionFailedEvent from .conversation_item_input_audio_transcription_completed_event import ( ConversationItemInputAudioTranscriptionCompletedEvent, ) __all__ = [ "RealtimeServerEvent", "ConversationItemRetrieved", "OutputAudioBufferStarted", "OutputAudioBufferStopped", "OutputAudioBufferCleared", ] class ConversationItemRetrieved(BaseModel): """Returned when a conversation item is retrieved with `conversation.item.retrieve`. This is provided as a way to fetch the server's representation of an item, for example to get access to the post-processed audio data after noise cancellation and VAD. It includes the full content of the Item, including audio data. """ event_id: str """The unique ID of the server event.""" item: ConversationItem """A single item within a Realtime conversation.""" type: Literal["conversation.item.retrieved"] """The event type, must be `conversation.item.retrieved`.""" class OutputAudioBufferStarted(BaseModel): """ **WebRTC/SIP Only:** Emitted when the server begins streaming audio to the client. This event is emitted after an audio content part has been added (`response.content_part.added`) to the response. [Learn more](https://platform.openai.com/docs/guides/realtime-conversations#client-and-server-events-for-audio-in-webrtc). """ event_id: str """The unique ID of the server event.""" response_id: str """The unique ID of the response that produced the audio.""" type: Literal["output_audio_buffer.started"] """The event type, must be `output_audio_buffer.started`.""" class OutputAudioBufferStopped(BaseModel): """ **WebRTC/SIP Only:** Emitted when the output audio buffer has been completely drained on the server, and no more audio is forthcoming. This event is emitted after the full response data has been sent to the client (`response.done`). [Learn more](https://platform.openai.com/docs/guides/realtime-conversations#client-and-server-events-for-audio-in-webrtc). """ event_id: str """The unique ID of the server event.""" response_id: str """The unique ID of the response that produced the audio.""" type: Literal["output_audio_buffer.stopped"] """The event type, must be `output_audio_buffer.stopped`.""" class OutputAudioBufferCleared(BaseModel): """**WebRTC/SIP Only:** Emitted when the output audio buffer is cleared. This happens either in VAD mode when the user has interrupted (`input_audio_buffer.speech_started`), or when the client has emitted the `output_audio_buffer.clear` event to manually cut off the current audio response. [Learn more](https://platform.openai.com/docs/guides/realtime-conversations#client-and-server-events-for-audio-in-webrtc). """ event_id: str """The unique ID of the server event.""" response_id: str """The unique ID of the response that produced the audio.""" type: Literal["output_audio_buffer.cleared"] """The event type, must be `output_audio_buffer.cleared`.""" RealtimeServerEvent: TypeAlias = Annotated[ Union[ ConversationCreatedEvent, ConversationItemCreatedEvent, ConversationItemDeletedEvent, ConversationItemInputAudioTranscriptionCompletedEvent, ConversationItemInputAudioTranscriptionDeltaEvent, ConversationItemInputAudioTranscriptionFailedEvent, ConversationItemRetrieved, ConversationItemTruncatedEvent, RealtimeErrorEvent, InputAudioBufferClearedEvent, InputAudioBufferCommittedEvent, InputAudioBufferDtmfEventReceivedEvent, InputAudioBufferSpeechStartedEvent, InputAudioBufferSpeechStoppedEvent, RateLimitsUpdatedEvent, ResponseAudioDeltaEvent, ResponseAudioDoneEvent, ResponseAudioTranscriptDeltaEvent, ResponseAudioTranscriptDoneEvent, ResponseContentPartAddedEvent, ResponseContentPartDoneEvent, ResponseCreatedEvent, ResponseDoneEvent, ResponseFunctionCallArgumentsDeltaEvent, ResponseFunctionCallArgumentsDoneEvent, ResponseOutputItemAddedEvent, ResponseOutputItemDoneEvent, ResponseTextDeltaEvent, ResponseTextDoneEvent, SessionCreatedEvent, SessionUpdatedEvent, OutputAudioBufferStarted, OutputAudioBufferStopped, OutputAudioBufferCleared, ConversationItemAdded, ConversationItemDone, InputAudioBufferTimeoutTriggered, ConversationItemInputAudioTranscriptionSegment, McpListToolsInProgress, McpListToolsCompleted, McpListToolsFailed, ResponseMcpCallArgumentsDelta, ResponseMcpCallArgumentsDone, ResponseMcpCallInProgress, ResponseMcpCallCompleted, ResponseMcpCallFailed, ], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/types/realtime/realtime_session_client_secret.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from ..._models import BaseModel __all__ = ["RealtimeSessionClientSecret"] class RealtimeSessionClientSecret(BaseModel): """Ephemeral key returned by the API.""" expires_at: int """Timestamp for when the token expires. Currently, all tokens expire after one minute. """ value: str """ Ephemeral key usable in client environments to authenticate connections to the Realtime API. Use this in client-side environments rather than a standard API token, which should only be used server-side. """ ================================================ FILE: src/openai/types/realtime/realtime_session_create_request.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal from ..._models import BaseModel from .realtime_truncation import RealtimeTruncation from .realtime_audio_config import RealtimeAudioConfig from .realtime_tools_config import RealtimeToolsConfig from .realtime_tracing_config import RealtimeTracingConfig from ..responses.response_prompt import ResponsePrompt from .realtime_tool_choice_config import RealtimeToolChoiceConfig __all__ = ["RealtimeSessionCreateRequest"] class RealtimeSessionCreateRequest(BaseModel): """Realtime session object configuration.""" type: Literal["realtime"] """The type of session to create. Always `realtime` for the Realtime API.""" audio: Optional[RealtimeAudioConfig] = None """Configuration for input and output audio.""" include: Optional[List[Literal["item.input_audio_transcription.logprobs"]]] = None """Additional fields to include in server outputs. `item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription. """ instructions: Optional[str] = None """The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. "be extremely succinct", "act friendly", "here are examples of good responses") and on audio behavior (e.g. "talk quickly", "inject emotion into your voice", "laugh frequently"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior. Note that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session. """ max_output_tokens: Union[int, Literal["inf"], None] = None """ Maximum number of output tokens for a single assistant response, inclusive of tool calls. Provide an integer between 1 and 4096 to limit output tokens, or `inf` for the maximum available tokens for a given model. Defaults to `inf`. """ model: Union[ str, Literal[ "gpt-realtime", "gpt-realtime-1.5", "gpt-realtime-2025-08-28", "gpt-4o-realtime-preview", "gpt-4o-realtime-preview-2024-10-01", "gpt-4o-realtime-preview-2024-12-17", "gpt-4o-realtime-preview-2025-06-03", "gpt-4o-mini-realtime-preview", "gpt-4o-mini-realtime-preview-2024-12-17", "gpt-realtime-mini", "gpt-realtime-mini-2025-10-06", "gpt-realtime-mini-2025-12-15", "gpt-audio-1.5", "gpt-audio-mini", "gpt-audio-mini-2025-10-06", "gpt-audio-mini-2025-12-15", ], None, ] = None """The Realtime model used for this session.""" output_modalities: Optional[List[Literal["text", "audio"]]] = None """The set of modalities the model can respond with. It defaults to `["audio"]`, indicating that the model will respond with audio plus a transcript. `["text"]` can be used to make the model respond with text only. It is not possible to request both `text` and `audio` at the same time. """ prompt: Optional[ResponsePrompt] = None """ Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). """ tool_choice: Optional[RealtimeToolChoiceConfig] = None """How the model chooses tools. Provide one of the string modes or force a specific function/MCP tool. """ tools: Optional[RealtimeToolsConfig] = None """Tools available to the model.""" tracing: Optional[RealtimeTracingConfig] = None """ Realtime API can write session traces to the [Traces Dashboard](/logs?api=traces). Set to null to disable tracing. Once tracing is enabled for a session, the configuration cannot be modified. `auto` will create a trace for the session with default values for the workflow name, group id, and metadata. """ truncation: Optional[RealtimeTruncation] = None """ When the number of tokens in a conversation exceeds the model's input token limit, the conversation be truncated, meaning messages (starting from the oldest) will not be included in the model's context. A 32k context model with 4,096 max output tokens can only include 28,224 tokens in the context before truncation occurs. Clients can configure truncation behavior to truncate with a lower max token limit, which is an effective way to control token usage and cost. Truncation will reduce the number of cached tokens on the next turn (busting the cache), since messages are dropped from the beginning of the context. However, clients can also configure truncation to retain messages up to a fraction of the maximum context size, which will reduce the need for future truncations and thus improve the cache rate. Truncation can be disabled entirely, which means the server will never truncate but would instead return an error if the conversation exceeds the model's input token limit. """ ================================================ FILE: src/openai/types/realtime/realtime_session_create_request_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List, Union, Optional from typing_extensions import Literal, Required, TypedDict from .realtime_truncation_param import RealtimeTruncationParam from .realtime_audio_config_param import RealtimeAudioConfigParam from .realtime_tools_config_param import RealtimeToolsConfigParam from .realtime_tracing_config_param import RealtimeTracingConfigParam from ..responses.response_prompt_param import ResponsePromptParam from .realtime_tool_choice_config_param import RealtimeToolChoiceConfigParam __all__ = ["RealtimeSessionCreateRequestParam"] class RealtimeSessionCreateRequestParam(TypedDict, total=False): """Realtime session object configuration.""" type: Required[Literal["realtime"]] """The type of session to create. Always `realtime` for the Realtime API.""" audio: RealtimeAudioConfigParam """Configuration for input and output audio.""" include: List[Literal["item.input_audio_transcription.logprobs"]] """Additional fields to include in server outputs. `item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription. """ instructions: str """The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. "be extremely succinct", "act friendly", "here are examples of good responses") and on audio behavior (e.g. "talk quickly", "inject emotion into your voice", "laugh frequently"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior. Note that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session. """ max_output_tokens: Union[int, Literal["inf"]] """ Maximum number of output tokens for a single assistant response, inclusive of tool calls. Provide an integer between 1 and 4096 to limit output tokens, or `inf` for the maximum available tokens for a given model. Defaults to `inf`. """ model: Union[ str, Literal[ "gpt-realtime", "gpt-realtime-1.5", "gpt-realtime-2025-08-28", "gpt-4o-realtime-preview", "gpt-4o-realtime-preview-2024-10-01", "gpt-4o-realtime-preview-2024-12-17", "gpt-4o-realtime-preview-2025-06-03", "gpt-4o-mini-realtime-preview", "gpt-4o-mini-realtime-preview-2024-12-17", "gpt-realtime-mini", "gpt-realtime-mini-2025-10-06", "gpt-realtime-mini-2025-12-15", "gpt-audio-1.5", "gpt-audio-mini", "gpt-audio-mini-2025-10-06", "gpt-audio-mini-2025-12-15", ], ] """The Realtime model used for this session.""" output_modalities: List[Literal["text", "audio"]] """The set of modalities the model can respond with. It defaults to `["audio"]`, indicating that the model will respond with audio plus a transcript. `["text"]` can be used to make the model respond with text only. It is not possible to request both `text` and `audio` at the same time. """ prompt: Optional[ResponsePromptParam] """ Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). """ tool_choice: RealtimeToolChoiceConfigParam """How the model chooses tools. Provide one of the string modes or force a specific function/MCP tool. """ tools: RealtimeToolsConfigParam """Tools available to the model.""" tracing: Optional[RealtimeTracingConfigParam] """ Realtime API can write session traces to the [Traces Dashboard](/logs?api=traces). Set to null to disable tracing. Once tracing is enabled for a session, the configuration cannot be modified. `auto` will create a trace for the session with default values for the workflow name, group id, and metadata. """ truncation: RealtimeTruncationParam """ When the number of tokens in a conversation exceeds the model's input token limit, the conversation be truncated, meaning messages (starting from the oldest) will not be included in the model's context. A 32k context model with 4,096 max output tokens can only include 28,224 tokens in the context before truncation occurs. Clients can configure truncation behavior to truncate with a lower max token limit, which is an effective way to control token usage and cost. Truncation will reduce the number of cached tokens on the next turn (busting the cache), since messages are dropped from the beginning of the context. However, clients can also configure truncation to retain messages up to a fraction of the maximum context size, which will reduce the need for future truncations and thus improve the cache rate. Truncation can be disabled entirely, which means the server will never truncate but would instead return an error if the conversation exceeds the model's input token limit. """ ================================================ FILE: src/openai/types/realtime/realtime_session_create_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .audio_transcription import AudioTranscription from .realtime_truncation import RealtimeTruncation from .noise_reduction_type import NoiseReductionType from .realtime_audio_formats import RealtimeAudioFormats from .realtime_function_tool import RealtimeFunctionTool from ..responses.response_prompt import ResponsePrompt from ..responses.tool_choice_mcp import ToolChoiceMcp from ..responses.tool_choice_options import ToolChoiceOptions from .realtime_session_client_secret import RealtimeSessionClientSecret from ..responses.tool_choice_function import ToolChoiceFunction __all__ = [ "RealtimeSessionCreateResponse", "Audio", "AudioInput", "AudioInputNoiseReduction", "AudioInputTurnDetection", "AudioInputTurnDetectionServerVad", "AudioInputTurnDetectionSemanticVad", "AudioOutput", "ToolChoice", "Tool", "ToolMcpTool", "ToolMcpToolAllowedTools", "ToolMcpToolAllowedToolsMcpToolFilter", "ToolMcpToolRequireApproval", "ToolMcpToolRequireApprovalMcpToolApprovalFilter", "ToolMcpToolRequireApprovalMcpToolApprovalFilterAlways", "ToolMcpToolRequireApprovalMcpToolApprovalFilterNever", "Tracing", "TracingTracingConfiguration", ] class AudioInputNoiseReduction(BaseModel): """Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. """ type: Optional[NoiseReductionType] = None """Type of noise reduction. `near_field` is for close-talking microphones such as headphones, `far_field` is for far-field microphones such as laptop or conference room microphones. """ class AudioInputTurnDetectionServerVad(BaseModel): """ Server-side voice activity detection (VAD) which flips on when user speech is detected and off after a period of silence. """ type: Literal["server_vad"] """Type of turn detection, `server_vad` to turn on simple Server VAD.""" create_response: Optional[bool] = None """Whether or not to automatically generate a response when a VAD stop event occurs. If `interrupt_response` is set to `false` this may fail to create a response if the model is already responding. If both `create_response` and `interrupt_response` are set to `false`, the model will never respond automatically but VAD events will still be emitted. """ idle_timeout_ms: Optional[int] = None """Optional timeout after which a model response will be triggered automatically. This is useful for situations in which a long pause from the user is unexpected, such as a phone call. The model will effectively prompt the user to continue the conversation based on the current context. The timeout value will be applied after the last model response's audio has finished playing, i.e. it's set to the `response.done` time plus audio playback duration. An `input_audio_buffer.timeout_triggered` event (plus events associated with the Response) will be emitted when the timeout is reached. Idle timeout is currently only supported for `server_vad` mode. """ interrupt_response: Optional[bool] = None """ Whether or not to automatically interrupt (cancel) any ongoing response with output to the default conversation (i.e. `conversation` of `auto`) when a VAD start event occurs. If `true` then the response will be cancelled, otherwise it will continue until complete. If both `create_response` and `interrupt_response` are set to `false`, the model will never respond automatically but VAD events will still be emitted. """ prefix_padding_ms: Optional[int] = None """Used only for `server_vad` mode. Amount of audio to include before the VAD detected speech (in milliseconds). Defaults to 300ms. """ silence_duration_ms: Optional[int] = None """Used only for `server_vad` mode. Duration of silence to detect speech stop (in milliseconds). Defaults to 500ms. With shorter values the model will respond more quickly, but may jump in on short pauses from the user. """ threshold: Optional[float] = None """Used only for `server_vad` mode. Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A higher threshold will require louder audio to activate the model, and thus might perform better in noisy environments. """ class AudioInputTurnDetectionSemanticVad(BaseModel): """ Server-side semantic turn detection which uses a model to determine when the user has finished speaking. """ type: Literal["semantic_vad"] """Type of turn detection, `semantic_vad` to turn on Semantic VAD.""" create_response: Optional[bool] = None """ Whether or not to automatically generate a response when a VAD stop event occurs. """ eagerness: Optional[Literal["low", "medium", "high", "auto"]] = None """Used only for `semantic_vad` mode. The eagerness of the model to respond. `low` will wait longer for the user to continue speaking, `high` will respond more quickly. `auto` is the default and is equivalent to `medium`. `low`, `medium`, and `high` have max timeouts of 8s, 4s, and 2s respectively. """ interrupt_response: Optional[bool] = None """ Whether or not to automatically interrupt any ongoing response with output to the default conversation (i.e. `conversation` of `auto`) when a VAD start event occurs. """ AudioInputTurnDetection: TypeAlias = Annotated[ Union[AudioInputTurnDetectionServerVad, AudioInputTurnDetectionSemanticVad, None], PropertyInfo(discriminator="type"), ] class AudioInput(BaseModel): format: Optional[RealtimeAudioFormats] = None """The format of the input audio.""" noise_reduction: Optional[AudioInputNoiseReduction] = None """Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. """ transcription: Optional[AudioTranscription] = None """ Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](https://platform.openai.com/docs/api-reference/audio/createTranscription) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service. """ turn_detection: Optional[AudioInputTurnDetection] = None """Configuration for turn detection, ether Server VAD or Semantic VAD. This can be set to `null` to turn off, in which case the client must manually trigger model response. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. Semantic VAD is more advanced and uses a turn detection model (in conjunction with VAD) to semantically estimate whether the user has finished speaking, then dynamically sets a timeout based on this probability. For example, if user audio trails off with "uhhm", the model will score a low probability of turn end and wait longer for the user to continue speaking. This can be useful for more natural conversations, but may have a higher latency. """ class AudioOutput(BaseModel): format: Optional[RealtimeAudioFormats] = None """The format of the output audio.""" speed: Optional[float] = None """ The speed of the model's spoken response as a multiple of the original speed. 1.0 is the default speed. 0.25 is the minimum speed. 1.5 is the maximum speed. This value can only be changed in between model turns, not while a response is in progress. This parameter is a post-processing adjustment to the audio after it is generated, it's also possible to prompt the model to speak faster or slower. """ voice: Union[ str, Literal["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse", "marin", "cedar"], None ] = None """The voice the model uses to respond. Voice cannot be changed during the session once the model has responded with audio at least once. Current voice options are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, `verse`, `marin`, and `cedar`. We recommend `marin` and `cedar` for best quality. """ class Audio(BaseModel): """Configuration for input and output audio.""" input: Optional[AudioInput] = None output: Optional[AudioOutput] = None ToolChoice: TypeAlias = Union[ToolChoiceOptions, ToolChoiceFunction, ToolChoiceMcp] class ToolMcpToolAllowedToolsMcpToolFilter(BaseModel): """A filter object to specify which tools are allowed.""" read_only: Optional[bool] = None """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: Optional[List[str]] = None """List of allowed tool names.""" ToolMcpToolAllowedTools: TypeAlias = Union[List[str], ToolMcpToolAllowedToolsMcpToolFilter, None] class ToolMcpToolRequireApprovalMcpToolApprovalFilterAlways(BaseModel): """A filter object to specify which tools are allowed.""" read_only: Optional[bool] = None """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: Optional[List[str]] = None """List of allowed tool names.""" class ToolMcpToolRequireApprovalMcpToolApprovalFilterNever(BaseModel): """A filter object to specify which tools are allowed.""" read_only: Optional[bool] = None """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: Optional[List[str]] = None """List of allowed tool names.""" class ToolMcpToolRequireApprovalMcpToolApprovalFilter(BaseModel): """Specify which of the MCP server's tools require approval. Can be `always`, `never`, or a filter object associated with tools that require approval. """ always: Optional[ToolMcpToolRequireApprovalMcpToolApprovalFilterAlways] = None """A filter object to specify which tools are allowed.""" never: Optional[ToolMcpToolRequireApprovalMcpToolApprovalFilterNever] = None """A filter object to specify which tools are allowed.""" ToolMcpToolRequireApproval: TypeAlias = Union[ ToolMcpToolRequireApprovalMcpToolApprovalFilter, Literal["always", "never"], None ] class ToolMcpTool(BaseModel): """ Give the model access to additional tools via remote Model Context Protocol (MCP) servers. [Learn more about MCP](https://platform.openai.com/docs/guides/tools-remote-mcp). """ server_label: str """A label for this MCP server, used to identify it in tool calls.""" type: Literal["mcp"] """The type of the MCP tool. Always `mcp`.""" allowed_tools: Optional[ToolMcpToolAllowedTools] = None """List of allowed tool names or a filter object.""" authorization: Optional[str] = None """ An OAuth access token that can be used with a remote MCP server, either with a custom MCP server URL or a service connector. Your application must handle the OAuth authorization flow and provide the token here. """ connector_id: Optional[ Literal[ "connector_dropbox", "connector_gmail", "connector_googlecalendar", "connector_googledrive", "connector_microsoftteams", "connector_outlookcalendar", "connector_outlookemail", "connector_sharepoint", ] ] = None """Identifier for service connectors, like those available in ChatGPT. One of `server_url` or `connector_id` must be provided. Learn more about service connectors [here](https://platform.openai.com/docs/guides/tools-remote-mcp#connectors). Currently supported `connector_id` values are: - Dropbox: `connector_dropbox` - Gmail: `connector_gmail` - Google Calendar: `connector_googlecalendar` - Google Drive: `connector_googledrive` - Microsoft Teams: `connector_microsoftteams` - Outlook Calendar: `connector_outlookcalendar` - Outlook Email: `connector_outlookemail` - SharePoint: `connector_sharepoint` """ defer_loading: Optional[bool] = None """Whether this MCP tool is deferred and discovered via tool search.""" headers: Optional[Dict[str, str]] = None """Optional HTTP headers to send to the MCP server. Use for authentication or other purposes. """ require_approval: Optional[ToolMcpToolRequireApproval] = None """Specify which of the MCP server's tools require approval.""" server_description: Optional[str] = None """Optional description of the MCP server, used to provide more context.""" server_url: Optional[str] = None """The URL for the MCP server. One of `server_url` or `connector_id` must be provided. """ Tool: TypeAlias = Union[RealtimeFunctionTool, ToolMcpTool] class TracingTracingConfiguration(BaseModel): """Granular configuration for tracing.""" group_id: Optional[str] = None """ The group id to attach to this trace to enable filtering and grouping in the Traces Dashboard. """ metadata: Optional[object] = None """ The arbitrary metadata to attach to this trace to enable filtering in the Traces Dashboard. """ workflow_name: Optional[str] = None """The name of the workflow to attach to this trace. This is used to name the trace in the Traces Dashboard. """ Tracing: TypeAlias = Union[Literal["auto"], TracingTracingConfiguration, None] class RealtimeSessionCreateResponse(BaseModel): """A new Realtime session configuration, with an ephemeral key. Default TTL for keys is one minute. """ client_secret: RealtimeSessionClientSecret """Ephemeral key returned by the API.""" type: Literal["realtime"] """The type of session to create. Always `realtime` for the Realtime API.""" audio: Optional[Audio] = None """Configuration for input and output audio.""" include: Optional[List[Literal["item.input_audio_transcription.logprobs"]]] = None """Additional fields to include in server outputs. `item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription. """ instructions: Optional[str] = None """The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. "be extremely succinct", "act friendly", "here are examples of good responses") and on audio behavior (e.g. "talk quickly", "inject emotion into your voice", "laugh frequently"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior. Note that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session. """ max_output_tokens: Union[int, Literal["inf"], None] = None """ Maximum number of output tokens for a single assistant response, inclusive of tool calls. Provide an integer between 1 and 4096 to limit output tokens, or `inf` for the maximum available tokens for a given model. Defaults to `inf`. """ model: Union[ str, Literal[ "gpt-realtime", "gpt-realtime-1.5", "gpt-realtime-2025-08-28", "gpt-4o-realtime-preview", "gpt-4o-realtime-preview-2024-10-01", "gpt-4o-realtime-preview-2024-12-17", "gpt-4o-realtime-preview-2025-06-03", "gpt-4o-mini-realtime-preview", "gpt-4o-mini-realtime-preview-2024-12-17", "gpt-realtime-mini", "gpt-realtime-mini-2025-10-06", "gpt-realtime-mini-2025-12-15", "gpt-audio-1.5", "gpt-audio-mini", "gpt-audio-mini-2025-10-06", "gpt-audio-mini-2025-12-15", ], None, ] = None """The Realtime model used for this session.""" output_modalities: Optional[List[Literal["text", "audio"]]] = None """The set of modalities the model can respond with. It defaults to `["audio"]`, indicating that the model will respond with audio plus a transcript. `["text"]` can be used to make the model respond with text only. It is not possible to request both `text` and `audio` at the same time. """ prompt: Optional[ResponsePrompt] = None """ Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). """ tool_choice: Optional[ToolChoice] = None """How the model chooses tools. Provide one of the string modes or force a specific function/MCP tool. """ tools: Optional[List[Tool]] = None """Tools available to the model.""" tracing: Optional[Tracing] = None """ Realtime API can write session traces to the [Traces Dashboard](/logs?api=traces). Set to null to disable tracing. Once tracing is enabled for a session, the configuration cannot be modified. `auto` will create a trace for the session with default values for the workflow name, group id, and metadata. """ truncation: Optional[RealtimeTruncation] = None """ When the number of tokens in a conversation exceeds the model's input token limit, the conversation be truncated, meaning messages (starting from the oldest) will not be included in the model's context. A 32k context model with 4,096 max output tokens can only include 28,224 tokens in the context before truncation occurs. Clients can configure truncation behavior to truncate with a lower max token limit, which is an effective way to control token usage and cost. Truncation will reduce the number of cached tokens on the next turn (busting the cache), since messages are dropped from the beginning of the context. However, clients can also configure truncation to retain messages up to a fraction of the maximum context size, which will reduce the need for future truncations and thus improve the cache rate. Truncation can be disabled entirely, which means the server will never truncate but would instead return an error if the conversation exceeds the model's input token limit. """ ================================================ FILE: src/openai/types/realtime/realtime_tool_choice_config.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import TypeAlias from ..responses.tool_choice_mcp import ToolChoiceMcp from ..responses.tool_choice_options import ToolChoiceOptions from ..responses.tool_choice_function import ToolChoiceFunction __all__ = ["RealtimeToolChoiceConfig"] RealtimeToolChoiceConfig: TypeAlias = Union[ToolChoiceOptions, ToolChoiceFunction, ToolChoiceMcp] ================================================ FILE: src/openai/types/realtime/realtime_tool_choice_config_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import TypeAlias from ..responses.tool_choice_options import ToolChoiceOptions from ..responses.tool_choice_mcp_param import ToolChoiceMcpParam from ..responses.tool_choice_function_param import ToolChoiceFunctionParam __all__ = ["RealtimeToolChoiceConfigParam"] RealtimeToolChoiceConfigParam: TypeAlias = Union[ToolChoiceOptions, ToolChoiceFunctionParam, ToolChoiceMcpParam] ================================================ FILE: src/openai/types/realtime/realtime_tools_config.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List from typing_extensions import TypeAlias from .realtime_tools_config_union import RealtimeToolsConfigUnion __all__ = ["RealtimeToolsConfig"] RealtimeToolsConfig: TypeAlias = List[RealtimeToolsConfigUnion] ================================================ FILE: src/openai/types/realtime/realtime_tools_config_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, List, Union, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import SequenceNotStr from .realtime_function_tool_param import RealtimeFunctionToolParam __all__ = [ "RealtimeToolsConfigParam", "RealtimeToolsConfigUnionParam", "Mcp", "McpAllowedTools", "McpAllowedToolsMcpToolFilter", "McpRequireApproval", "McpRequireApprovalMcpToolApprovalFilter", "McpRequireApprovalMcpToolApprovalFilterAlways", "McpRequireApprovalMcpToolApprovalFilterNever", ] class McpAllowedToolsMcpToolFilter(TypedDict, total=False): """A filter object to specify which tools are allowed.""" read_only: bool """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: SequenceNotStr[str] """List of allowed tool names.""" McpAllowedTools: TypeAlias = Union[SequenceNotStr[str], McpAllowedToolsMcpToolFilter] class McpRequireApprovalMcpToolApprovalFilterAlways(TypedDict, total=False): """A filter object to specify which tools are allowed.""" read_only: bool """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: SequenceNotStr[str] """List of allowed tool names.""" class McpRequireApprovalMcpToolApprovalFilterNever(TypedDict, total=False): """A filter object to specify which tools are allowed.""" read_only: bool """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: SequenceNotStr[str] """List of allowed tool names.""" class McpRequireApprovalMcpToolApprovalFilter(TypedDict, total=False): """Specify which of the MCP server's tools require approval. Can be `always`, `never`, or a filter object associated with tools that require approval. """ always: McpRequireApprovalMcpToolApprovalFilterAlways """A filter object to specify which tools are allowed.""" never: McpRequireApprovalMcpToolApprovalFilterNever """A filter object to specify which tools are allowed.""" McpRequireApproval: TypeAlias = Union[McpRequireApprovalMcpToolApprovalFilter, Literal["always", "never"]] class Mcp(TypedDict, total=False): """ Give the model access to additional tools via remote Model Context Protocol (MCP) servers. [Learn more about MCP](https://platform.openai.com/docs/guides/tools-remote-mcp). """ server_label: Required[str] """A label for this MCP server, used to identify it in tool calls.""" type: Required[Literal["mcp"]] """The type of the MCP tool. Always `mcp`.""" allowed_tools: Optional[McpAllowedTools] """List of allowed tool names or a filter object.""" authorization: str """ An OAuth access token that can be used with a remote MCP server, either with a custom MCP server URL or a service connector. Your application must handle the OAuth authorization flow and provide the token here. """ connector_id: Literal[ "connector_dropbox", "connector_gmail", "connector_googlecalendar", "connector_googledrive", "connector_microsoftteams", "connector_outlookcalendar", "connector_outlookemail", "connector_sharepoint", ] """Identifier for service connectors, like those available in ChatGPT. One of `server_url` or `connector_id` must be provided. Learn more about service connectors [here](https://platform.openai.com/docs/guides/tools-remote-mcp#connectors). Currently supported `connector_id` values are: - Dropbox: `connector_dropbox` - Gmail: `connector_gmail` - Google Calendar: `connector_googlecalendar` - Google Drive: `connector_googledrive` - Microsoft Teams: `connector_microsoftteams` - Outlook Calendar: `connector_outlookcalendar` - Outlook Email: `connector_outlookemail` - SharePoint: `connector_sharepoint` """ defer_loading: bool """Whether this MCP tool is deferred and discovered via tool search.""" headers: Optional[Dict[str, str]] """Optional HTTP headers to send to the MCP server. Use for authentication or other purposes. """ require_approval: Optional[McpRequireApproval] """Specify which of the MCP server's tools require approval.""" server_description: str """Optional description of the MCP server, used to provide more context.""" server_url: str """The URL for the MCP server. One of `server_url` or `connector_id` must be provided. """ RealtimeToolsConfigUnionParam: TypeAlias = Union[RealtimeFunctionToolParam, Mcp] RealtimeToolsConfigParam: TypeAlias = List[RealtimeToolsConfigUnionParam] ================================================ FILE: src/openai/types/realtime/realtime_tools_config_union.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .realtime_function_tool import RealtimeFunctionTool __all__ = [ "RealtimeToolsConfigUnion", "Mcp", "McpAllowedTools", "McpAllowedToolsMcpToolFilter", "McpRequireApproval", "McpRequireApprovalMcpToolApprovalFilter", "McpRequireApprovalMcpToolApprovalFilterAlways", "McpRequireApprovalMcpToolApprovalFilterNever", ] class McpAllowedToolsMcpToolFilter(BaseModel): """A filter object to specify which tools are allowed.""" read_only: Optional[bool] = None """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: Optional[List[str]] = None """List of allowed tool names.""" McpAllowedTools: TypeAlias = Union[List[str], McpAllowedToolsMcpToolFilter, None] class McpRequireApprovalMcpToolApprovalFilterAlways(BaseModel): """A filter object to specify which tools are allowed.""" read_only: Optional[bool] = None """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: Optional[List[str]] = None """List of allowed tool names.""" class McpRequireApprovalMcpToolApprovalFilterNever(BaseModel): """A filter object to specify which tools are allowed.""" read_only: Optional[bool] = None """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: Optional[List[str]] = None """List of allowed tool names.""" class McpRequireApprovalMcpToolApprovalFilter(BaseModel): """Specify which of the MCP server's tools require approval. Can be `always`, `never`, or a filter object associated with tools that require approval. """ always: Optional[McpRequireApprovalMcpToolApprovalFilterAlways] = None """A filter object to specify which tools are allowed.""" never: Optional[McpRequireApprovalMcpToolApprovalFilterNever] = None """A filter object to specify which tools are allowed.""" McpRequireApproval: TypeAlias = Union[McpRequireApprovalMcpToolApprovalFilter, Literal["always", "never"], None] class Mcp(BaseModel): """ Give the model access to additional tools via remote Model Context Protocol (MCP) servers. [Learn more about MCP](https://platform.openai.com/docs/guides/tools-remote-mcp). """ server_label: str """A label for this MCP server, used to identify it in tool calls.""" type: Literal["mcp"] """The type of the MCP tool. Always `mcp`.""" allowed_tools: Optional[McpAllowedTools] = None """List of allowed tool names or a filter object.""" authorization: Optional[str] = None """ An OAuth access token that can be used with a remote MCP server, either with a custom MCP server URL or a service connector. Your application must handle the OAuth authorization flow and provide the token here. """ connector_id: Optional[ Literal[ "connector_dropbox", "connector_gmail", "connector_googlecalendar", "connector_googledrive", "connector_microsoftteams", "connector_outlookcalendar", "connector_outlookemail", "connector_sharepoint", ] ] = None """Identifier for service connectors, like those available in ChatGPT. One of `server_url` or `connector_id` must be provided. Learn more about service connectors [here](https://platform.openai.com/docs/guides/tools-remote-mcp#connectors). Currently supported `connector_id` values are: - Dropbox: `connector_dropbox` - Gmail: `connector_gmail` - Google Calendar: `connector_googlecalendar` - Google Drive: `connector_googledrive` - Microsoft Teams: `connector_microsoftteams` - Outlook Calendar: `connector_outlookcalendar` - Outlook Email: `connector_outlookemail` - SharePoint: `connector_sharepoint` """ defer_loading: Optional[bool] = None """Whether this MCP tool is deferred and discovered via tool search.""" headers: Optional[Dict[str, str]] = None """Optional HTTP headers to send to the MCP server. Use for authentication or other purposes. """ require_approval: Optional[McpRequireApproval] = None """Specify which of the MCP server's tools require approval.""" server_description: Optional[str] = None """Optional description of the MCP server, used to provide more context.""" server_url: Optional[str] = None """The URL for the MCP server. One of `server_url` or `connector_id` must be provided. """ RealtimeToolsConfigUnion: TypeAlias = Annotated[Union[RealtimeFunctionTool, Mcp], PropertyInfo(discriminator="type")] ================================================ FILE: src/openai/types/realtime/realtime_tools_config_union_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Union, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import SequenceNotStr from .realtime_function_tool_param import RealtimeFunctionToolParam __all__ = [ "RealtimeToolsConfigUnionParam", "Mcp", "McpAllowedTools", "McpAllowedToolsMcpToolFilter", "McpRequireApproval", "McpRequireApprovalMcpToolApprovalFilter", "McpRequireApprovalMcpToolApprovalFilterAlways", "McpRequireApprovalMcpToolApprovalFilterNever", ] class McpAllowedToolsMcpToolFilter(TypedDict, total=False): """A filter object to specify which tools are allowed.""" read_only: bool """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: SequenceNotStr[str] """List of allowed tool names.""" McpAllowedTools: TypeAlias = Union[SequenceNotStr[str], McpAllowedToolsMcpToolFilter] class McpRequireApprovalMcpToolApprovalFilterAlways(TypedDict, total=False): """A filter object to specify which tools are allowed.""" read_only: bool """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: SequenceNotStr[str] """List of allowed tool names.""" class McpRequireApprovalMcpToolApprovalFilterNever(TypedDict, total=False): """A filter object to specify which tools are allowed.""" read_only: bool """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: SequenceNotStr[str] """List of allowed tool names.""" class McpRequireApprovalMcpToolApprovalFilter(TypedDict, total=False): """Specify which of the MCP server's tools require approval. Can be `always`, `never`, or a filter object associated with tools that require approval. """ always: McpRequireApprovalMcpToolApprovalFilterAlways """A filter object to specify which tools are allowed.""" never: McpRequireApprovalMcpToolApprovalFilterNever """A filter object to specify which tools are allowed.""" McpRequireApproval: TypeAlias = Union[McpRequireApprovalMcpToolApprovalFilter, Literal["always", "never"]] class Mcp(TypedDict, total=False): """ Give the model access to additional tools via remote Model Context Protocol (MCP) servers. [Learn more about MCP](https://platform.openai.com/docs/guides/tools-remote-mcp). """ server_label: Required[str] """A label for this MCP server, used to identify it in tool calls.""" type: Required[Literal["mcp"]] """The type of the MCP tool. Always `mcp`.""" allowed_tools: Optional[McpAllowedTools] """List of allowed tool names or a filter object.""" authorization: str """ An OAuth access token that can be used with a remote MCP server, either with a custom MCP server URL or a service connector. Your application must handle the OAuth authorization flow and provide the token here. """ connector_id: Literal[ "connector_dropbox", "connector_gmail", "connector_googlecalendar", "connector_googledrive", "connector_microsoftteams", "connector_outlookcalendar", "connector_outlookemail", "connector_sharepoint", ] """Identifier for service connectors, like those available in ChatGPT. One of `server_url` or `connector_id` must be provided. Learn more about service connectors [here](https://platform.openai.com/docs/guides/tools-remote-mcp#connectors). Currently supported `connector_id` values are: - Dropbox: `connector_dropbox` - Gmail: `connector_gmail` - Google Calendar: `connector_googlecalendar` - Google Drive: `connector_googledrive` - Microsoft Teams: `connector_microsoftteams` - Outlook Calendar: `connector_outlookcalendar` - Outlook Email: `connector_outlookemail` - SharePoint: `connector_sharepoint` """ defer_loading: bool """Whether this MCP tool is deferred and discovered via tool search.""" headers: Optional[Dict[str, str]] """Optional HTTP headers to send to the MCP server. Use for authentication or other purposes. """ require_approval: Optional[McpRequireApproval] """Specify which of the MCP server's tools require approval.""" server_description: str """Optional description of the MCP server, used to provide more context.""" server_url: str """The URL for the MCP server. One of `server_url` or `connector_id` must be provided. """ RealtimeToolsConfigUnionParam: TypeAlias = Union[RealtimeFunctionToolParam, Mcp] ================================================ FILE: src/openai/types/realtime/realtime_tracing_config.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import Literal, TypeAlias from ..._models import BaseModel __all__ = ["RealtimeTracingConfig", "TracingConfiguration"] class TracingConfiguration(BaseModel): """Granular configuration for tracing.""" group_id: Optional[str] = None """ The group id to attach to this trace to enable filtering and grouping in the Traces Dashboard. """ metadata: Optional[object] = None """ The arbitrary metadata to attach to this trace to enable filtering in the Traces Dashboard. """ workflow_name: Optional[str] = None """The name of the workflow to attach to this trace. This is used to name the trace in the Traces Dashboard. """ RealtimeTracingConfig: TypeAlias = Union[Literal["auto"], TracingConfiguration, None] ================================================ FILE: src/openai/types/realtime/realtime_tracing_config_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, TypeAlias, TypedDict __all__ = ["RealtimeTracingConfigParam", "TracingConfiguration"] class TracingConfiguration(TypedDict, total=False): """Granular configuration for tracing.""" group_id: str """ The group id to attach to this trace to enable filtering and grouping in the Traces Dashboard. """ metadata: object """ The arbitrary metadata to attach to this trace to enable filtering in the Traces Dashboard. """ workflow_name: str """The name of the workflow to attach to this trace. This is used to name the trace in the Traces Dashboard. """ RealtimeTracingConfigParam: TypeAlias = Union[Literal["auto"], TracingConfiguration] ================================================ FILE: src/openai/types/realtime/realtime_transcription_session_audio.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from ..._models import BaseModel from .realtime_transcription_session_audio_input import RealtimeTranscriptionSessionAudioInput __all__ = ["RealtimeTranscriptionSessionAudio"] class RealtimeTranscriptionSessionAudio(BaseModel): """Configuration for input and output audio.""" input: Optional[RealtimeTranscriptionSessionAudioInput] = None ================================================ FILE: src/openai/types/realtime/realtime_transcription_session_audio_input.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from ..._models import BaseModel from .audio_transcription import AudioTranscription from .noise_reduction_type import NoiseReductionType from .realtime_audio_formats import RealtimeAudioFormats from .realtime_transcription_session_audio_input_turn_detection import ( RealtimeTranscriptionSessionAudioInputTurnDetection, ) __all__ = ["RealtimeTranscriptionSessionAudioInput", "NoiseReduction"] class NoiseReduction(BaseModel): """Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. """ type: Optional[NoiseReductionType] = None """Type of noise reduction. `near_field` is for close-talking microphones such as headphones, `far_field` is for far-field microphones such as laptop or conference room microphones. """ class RealtimeTranscriptionSessionAudioInput(BaseModel): format: Optional[RealtimeAudioFormats] = None """The PCM audio format. Only a 24kHz sample rate is supported.""" noise_reduction: Optional[NoiseReduction] = None """Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. """ transcription: Optional[AudioTranscription] = None """ Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](https://platform.openai.com/docs/api-reference/audio/createTranscription) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service. """ turn_detection: Optional[RealtimeTranscriptionSessionAudioInputTurnDetection] = None """Configuration for turn detection, ether Server VAD or Semantic VAD. This can be set to `null` to turn off, in which case the client must manually trigger model response. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. Semantic VAD is more advanced and uses a turn detection model (in conjunction with VAD) to semantically estimate whether the user has finished speaking, then dynamically sets a timeout based on this probability. For example, if user audio trails off with "uhhm", the model will score a low probability of turn end and wait longer for the user to continue speaking. This can be useful for more natural conversations, but may have a higher latency. """ ================================================ FILE: src/openai/types/realtime/realtime_transcription_session_audio_input_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import TypedDict from .noise_reduction_type import NoiseReductionType from .audio_transcription_param import AudioTranscriptionParam from .realtime_audio_formats_param import RealtimeAudioFormatsParam from .realtime_transcription_session_audio_input_turn_detection_param import ( RealtimeTranscriptionSessionAudioInputTurnDetectionParam, ) __all__ = ["RealtimeTranscriptionSessionAudioInputParam", "NoiseReduction"] class NoiseReduction(TypedDict, total=False): """Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. """ type: NoiseReductionType """Type of noise reduction. `near_field` is for close-talking microphones such as headphones, `far_field` is for far-field microphones such as laptop or conference room microphones. """ class RealtimeTranscriptionSessionAudioInputParam(TypedDict, total=False): format: RealtimeAudioFormatsParam """The PCM audio format. Only a 24kHz sample rate is supported.""" noise_reduction: NoiseReduction """Configuration for input audio noise reduction. This can be set to `null` to turn off. Noise reduction filters audio added to the input audio buffer before it is sent to VAD and the model. Filtering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio. """ transcription: AudioTranscriptionParam """ Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](https://platform.openai.com/docs/api-reference/audio/createTranscription) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service. """ turn_detection: Optional[RealtimeTranscriptionSessionAudioInputTurnDetectionParam] """Configuration for turn detection, ether Server VAD or Semantic VAD. This can be set to `null` to turn off, in which case the client must manually trigger model response. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. Semantic VAD is more advanced and uses a turn detection model (in conjunction with VAD) to semantically estimate whether the user has finished speaking, then dynamically sets a timeout based on this probability. For example, if user audio trails off with "uhhm", the model will score a low probability of turn end and wait longer for the user to continue speaking. This can be useful for more natural conversations, but may have a higher latency. """ ================================================ FILE: src/openai/types/realtime/realtime_transcription_session_audio_input_turn_detection.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = ["RealtimeTranscriptionSessionAudioInputTurnDetection", "ServerVad", "SemanticVad"] class ServerVad(BaseModel): """ Server-side voice activity detection (VAD) which flips on when user speech is detected and off after a period of silence. """ type: Literal["server_vad"] """Type of turn detection, `server_vad` to turn on simple Server VAD.""" create_response: Optional[bool] = None """Whether or not to automatically generate a response when a VAD stop event occurs. If `interrupt_response` is set to `false` this may fail to create a response if the model is already responding. If both `create_response` and `interrupt_response` are set to `false`, the model will never respond automatically but VAD events will still be emitted. """ idle_timeout_ms: Optional[int] = None """Optional timeout after which a model response will be triggered automatically. This is useful for situations in which a long pause from the user is unexpected, such as a phone call. The model will effectively prompt the user to continue the conversation based on the current context. The timeout value will be applied after the last model response's audio has finished playing, i.e. it's set to the `response.done` time plus audio playback duration. An `input_audio_buffer.timeout_triggered` event (plus events associated with the Response) will be emitted when the timeout is reached. Idle timeout is currently only supported for `server_vad` mode. """ interrupt_response: Optional[bool] = None """ Whether or not to automatically interrupt (cancel) any ongoing response with output to the default conversation (i.e. `conversation` of `auto`) when a VAD start event occurs. If `true` then the response will be cancelled, otherwise it will continue until complete. If both `create_response` and `interrupt_response` are set to `false`, the model will never respond automatically but VAD events will still be emitted. """ prefix_padding_ms: Optional[int] = None """Used only for `server_vad` mode. Amount of audio to include before the VAD detected speech (in milliseconds). Defaults to 300ms. """ silence_duration_ms: Optional[int] = None """Used only for `server_vad` mode. Duration of silence to detect speech stop (in milliseconds). Defaults to 500ms. With shorter values the model will respond more quickly, but may jump in on short pauses from the user. """ threshold: Optional[float] = None """Used only for `server_vad` mode. Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A higher threshold will require louder audio to activate the model, and thus might perform better in noisy environments. """ class SemanticVad(BaseModel): """ Server-side semantic turn detection which uses a model to determine when the user has finished speaking. """ type: Literal["semantic_vad"] """Type of turn detection, `semantic_vad` to turn on Semantic VAD.""" create_response: Optional[bool] = None """ Whether or not to automatically generate a response when a VAD stop event occurs. """ eagerness: Optional[Literal["low", "medium", "high", "auto"]] = None """Used only for `semantic_vad` mode. The eagerness of the model to respond. `low` will wait longer for the user to continue speaking, `high` will respond more quickly. `auto` is the default and is equivalent to `medium`. `low`, `medium`, and `high` have max timeouts of 8s, 4s, and 2s respectively. """ interrupt_response: Optional[bool] = None """ Whether or not to automatically interrupt any ongoing response with output to the default conversation (i.e. `conversation` of `auto`) when a VAD start event occurs. """ RealtimeTranscriptionSessionAudioInputTurnDetection: TypeAlias = Annotated[ Union[ServerVad, SemanticVad, None], PropertyInfo(discriminator="type") ] ================================================ FILE: src/openai/types/realtime/realtime_transcription_session_audio_input_turn_detection_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict __all__ = ["RealtimeTranscriptionSessionAudioInputTurnDetectionParam", "ServerVad", "SemanticVad"] class ServerVad(TypedDict, total=False): """ Server-side voice activity detection (VAD) which flips on when user speech is detected and off after a period of silence. """ type: Required[Literal["server_vad"]] """Type of turn detection, `server_vad` to turn on simple Server VAD.""" create_response: bool """Whether or not to automatically generate a response when a VAD stop event occurs. If `interrupt_response` is set to `false` this may fail to create a response if the model is already responding. If both `create_response` and `interrupt_response` are set to `false`, the model will never respond automatically but VAD events will still be emitted. """ idle_timeout_ms: Optional[int] """Optional timeout after which a model response will be triggered automatically. This is useful for situations in which a long pause from the user is unexpected, such as a phone call. The model will effectively prompt the user to continue the conversation based on the current context. The timeout value will be applied after the last model response's audio has finished playing, i.e. it's set to the `response.done` time plus audio playback duration. An `input_audio_buffer.timeout_triggered` event (plus events associated with the Response) will be emitted when the timeout is reached. Idle timeout is currently only supported for `server_vad` mode. """ interrupt_response: bool """ Whether or not to automatically interrupt (cancel) any ongoing response with output to the default conversation (i.e. `conversation` of `auto`) when a VAD start event occurs. If `true` then the response will be cancelled, otherwise it will continue until complete. If both `create_response` and `interrupt_response` are set to `false`, the model will never respond automatically but VAD events will still be emitted. """ prefix_padding_ms: int """Used only for `server_vad` mode. Amount of audio to include before the VAD detected speech (in milliseconds). Defaults to 300ms. """ silence_duration_ms: int """Used only for `server_vad` mode. Duration of silence to detect speech stop (in milliseconds). Defaults to 500ms. With shorter values the model will respond more quickly, but may jump in on short pauses from the user. """ threshold: float """Used only for `server_vad` mode. Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A higher threshold will require louder audio to activate the model, and thus might perform better in noisy environments. """ class SemanticVad(TypedDict, total=False): """ Server-side semantic turn detection which uses a model to determine when the user has finished speaking. """ type: Required[Literal["semantic_vad"]] """Type of turn detection, `semantic_vad` to turn on Semantic VAD.""" create_response: bool """ Whether or not to automatically generate a response when a VAD stop event occurs. """ eagerness: Literal["low", "medium", "high", "auto"] """Used only for `semantic_vad` mode. The eagerness of the model to respond. `low` will wait longer for the user to continue speaking, `high` will respond more quickly. `auto` is the default and is equivalent to `medium`. `low`, `medium`, and `high` have max timeouts of 8s, 4s, and 2s respectively. """ interrupt_response: bool """ Whether or not to automatically interrupt any ongoing response with output to the default conversation (i.e. `conversation` of `auto`) when a VAD start event occurs. """ RealtimeTranscriptionSessionAudioInputTurnDetectionParam: TypeAlias = Union[ServerVad, SemanticVad] ================================================ FILE: src/openai/types/realtime/realtime_transcription_session_audio_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import TypedDict from .realtime_transcription_session_audio_input_param import RealtimeTranscriptionSessionAudioInputParam __all__ = ["RealtimeTranscriptionSessionAudioParam"] class RealtimeTranscriptionSessionAudioParam(TypedDict, total=False): """Configuration for input and output audio.""" input: RealtimeTranscriptionSessionAudioInputParam ================================================ FILE: src/openai/types/realtime/realtime_transcription_session_create_request.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel from .realtime_transcription_session_audio import RealtimeTranscriptionSessionAudio __all__ = ["RealtimeTranscriptionSessionCreateRequest"] class RealtimeTranscriptionSessionCreateRequest(BaseModel): """Realtime transcription session object configuration.""" type: Literal["transcription"] """The type of session to create. Always `transcription` for transcription sessions. """ audio: Optional[RealtimeTranscriptionSessionAudio] = None """Configuration for input and output audio.""" include: Optional[List[Literal["item.input_audio_transcription.logprobs"]]] = None """Additional fields to include in server outputs. `item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription. """ ================================================ FILE: src/openai/types/realtime/realtime_transcription_session_create_request_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List from typing_extensions import Literal, Required, TypedDict from .realtime_transcription_session_audio_param import RealtimeTranscriptionSessionAudioParam __all__ = ["RealtimeTranscriptionSessionCreateRequestParam"] class RealtimeTranscriptionSessionCreateRequestParam(TypedDict, total=False): """Realtime transcription session object configuration.""" type: Required[Literal["transcription"]] """The type of session to create. Always `transcription` for transcription sessions. """ audio: RealtimeTranscriptionSessionAudioParam """Configuration for input and output audio.""" include: List[Literal["item.input_audio_transcription.logprobs"]] """Additional fields to include in server outputs. `item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription. """ ================================================ FILE: src/openai/types/realtime/realtime_transcription_session_create_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel from .audio_transcription import AudioTranscription from .noise_reduction_type import NoiseReductionType from .realtime_audio_formats import RealtimeAudioFormats from .realtime_transcription_session_turn_detection import RealtimeTranscriptionSessionTurnDetection __all__ = ["RealtimeTranscriptionSessionCreateResponse", "Audio", "AudioInput", "AudioInputNoiseReduction"] class AudioInputNoiseReduction(BaseModel): """Configuration for input audio noise reduction.""" type: Optional[NoiseReductionType] = None """Type of noise reduction. `near_field` is for close-talking microphones such as headphones, `far_field` is for far-field microphones such as laptop or conference room microphones. """ class AudioInput(BaseModel): format: Optional[RealtimeAudioFormats] = None """The PCM audio format. Only a 24kHz sample rate is supported.""" noise_reduction: Optional[AudioInputNoiseReduction] = None """Configuration for input audio noise reduction.""" transcription: Optional[AudioTranscription] = None """Configuration of the transcription model.""" turn_detection: Optional[RealtimeTranscriptionSessionTurnDetection] = None """Configuration for turn detection. Can be set to `null` to turn off. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. """ class Audio(BaseModel): """Configuration for input audio for the session.""" input: Optional[AudioInput] = None class RealtimeTranscriptionSessionCreateResponse(BaseModel): """A Realtime transcription session configuration object.""" id: str """Unique identifier for the session that looks like `sess_1234567890abcdef`.""" object: str """The object type. Always `realtime.transcription_session`.""" type: Literal["transcription"] """The type of session. Always `transcription` for transcription sessions.""" audio: Optional[Audio] = None """Configuration for input audio for the session.""" expires_at: Optional[int] = None """Expiration timestamp for the session, in seconds since epoch.""" include: Optional[List[Literal["item.input_audio_transcription.logprobs"]]] = None """Additional fields to include in server outputs. - `item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription. """ ================================================ FILE: src/openai/types/realtime/realtime_transcription_session_turn_detection.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from ..._models import BaseModel __all__ = ["RealtimeTranscriptionSessionTurnDetection"] class RealtimeTranscriptionSessionTurnDetection(BaseModel): """Configuration for turn detection. Can be set to `null` to turn off. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech. """ prefix_padding_ms: Optional[int] = None """Amount of audio to include before the VAD detected speech (in milliseconds). Defaults to 300ms. """ silence_duration_ms: Optional[int] = None """Duration of silence to detect speech stop (in milliseconds). Defaults to 500ms. With shorter values the model will respond more quickly, but may jump in on short pauses from the user. """ threshold: Optional[float] = None """Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A higher threshold will require louder audio to activate the model, and thus might perform better in noisy environments. """ type: Optional[str] = None """Type of turn detection, only `server_vad` is currently supported.""" ================================================ FILE: src/openai/types/realtime/realtime_truncation.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Literal, TypeAlias from .realtime_truncation_retention_ratio import RealtimeTruncationRetentionRatio __all__ = ["RealtimeTruncation"] RealtimeTruncation: TypeAlias = Union[Literal["auto", "disabled"], RealtimeTruncationRetentionRatio] ================================================ FILE: src/openai/types/realtime/realtime_truncation_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, TypeAlias from .realtime_truncation_retention_ratio_param import RealtimeTruncationRetentionRatioParam __all__ = ["RealtimeTruncationParam"] RealtimeTruncationParam: TypeAlias = Union[Literal["auto", "disabled"], RealtimeTruncationRetentionRatioParam] ================================================ FILE: src/openai/types/realtime/realtime_truncation_retention_ratio.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["RealtimeTruncationRetentionRatio", "TokenLimits"] class TokenLimits(BaseModel): """Optional custom token limits for this truncation strategy. If not provided, the model's default token limits will be used. """ post_instructions: Optional[int] = None """ Maximum tokens allowed in the conversation after instructions (which including tool definitions). For example, setting this to 5,000 would mean that truncation would occur when the conversation exceeds 5,000 tokens after instructions. This cannot be higher than the model's context window size minus the maximum output tokens. """ class RealtimeTruncationRetentionRatio(BaseModel): """ Retain a fraction of the conversation tokens when the conversation exceeds the input token limit. This allows you to amortize truncations across multiple turns, which can help improve cached token usage. """ retention_ratio: float """ Fraction of post-instruction conversation tokens to retain (`0.0` - `1.0`) when the conversation exceeds the input token limit. Setting this to `0.8` means that messages will be dropped until 80% of the maximum allowed tokens are used. This helps reduce the frequency of truncations and improve cache rates. """ type: Literal["retention_ratio"] """Use retention ratio truncation.""" token_limits: Optional[TokenLimits] = None """Optional custom token limits for this truncation strategy. If not provided, the model's default token limits will be used. """ ================================================ FILE: src/openai/types/realtime/realtime_truncation_retention_ratio_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["RealtimeTruncationRetentionRatioParam", "TokenLimits"] class TokenLimits(TypedDict, total=False): """Optional custom token limits for this truncation strategy. If not provided, the model's default token limits will be used. """ post_instructions: int """ Maximum tokens allowed in the conversation after instructions (which including tool definitions). For example, setting this to 5,000 would mean that truncation would occur when the conversation exceeds 5,000 tokens after instructions. This cannot be higher than the model's context window size minus the maximum output tokens. """ class RealtimeTruncationRetentionRatioParam(TypedDict, total=False): """ Retain a fraction of the conversation tokens when the conversation exceeds the input token limit. This allows you to amortize truncations across multiple turns, which can help improve cached token usage. """ retention_ratio: Required[float] """ Fraction of post-instruction conversation tokens to retain (`0.0` - `1.0`) when the conversation exceeds the input token limit. Setting this to `0.8` means that messages will be dropped until 80% of the maximum allowed tokens are used. This helps reduce the frequency of truncations and improve cache rates. """ type: Required[Literal["retention_ratio"]] """Use retention ratio truncation.""" token_limits: TokenLimits """Optional custom token limits for this truncation strategy. If not provided, the model's default token limits will be used. """ ================================================ FILE: src/openai/types/realtime/response_audio_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseAudioDeltaEvent"] class ResponseAudioDeltaEvent(BaseModel): """Returned when the model-generated audio is updated.""" content_index: int """The index of the content part in the item's content array.""" delta: str """Base64-encoded audio data delta.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item.""" output_index: int """The index of the output item in the response.""" response_id: str """The ID of the response.""" type: Literal["response.output_audio.delta"] """The event type, must be `response.output_audio.delta`.""" ================================================ FILE: src/openai/types/realtime/response_audio_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseAudioDoneEvent"] class ResponseAudioDoneEvent(BaseModel): """Returned when the model-generated audio is done. Also emitted when a Response is interrupted, incomplete, or cancelled. """ content_index: int """The index of the content part in the item's content array.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item.""" output_index: int """The index of the output item in the response.""" response_id: str """The ID of the response.""" type: Literal["response.output_audio.done"] """The event type, must be `response.output_audio.done`.""" ================================================ FILE: src/openai/types/realtime/response_audio_transcript_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseAudioTranscriptDeltaEvent"] class ResponseAudioTranscriptDeltaEvent(BaseModel): """Returned when the model-generated transcription of audio output is updated.""" content_index: int """The index of the content part in the item's content array.""" delta: str """The transcript delta.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item.""" output_index: int """The index of the output item in the response.""" response_id: str """The ID of the response.""" type: Literal["response.output_audio_transcript.delta"] """The event type, must be `response.output_audio_transcript.delta`.""" ================================================ FILE: src/openai/types/realtime/response_audio_transcript_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseAudioTranscriptDoneEvent"] class ResponseAudioTranscriptDoneEvent(BaseModel): """ Returned when the model-generated transcription of audio output is done streaming. Also emitted when a Response is interrupted, incomplete, or cancelled. """ content_index: int """The index of the content part in the item's content array.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item.""" output_index: int """The index of the output item in the response.""" response_id: str """The ID of the response.""" transcript: str """The final transcript of the audio.""" type: Literal["response.output_audio_transcript.done"] """The event type, must be `response.output_audio_transcript.done`.""" ================================================ FILE: src/openai/types/realtime/response_cancel_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseCancelEvent"] class ResponseCancelEvent(BaseModel): """Send this event to cancel an in-progress response. The server will respond with a `response.done` event with a status of `response.status=cancelled`. If there is no response to cancel, the server will respond with an error. It's safe to call `response.cancel` even if no response is in progress, an error will be returned the session will remain unaffected. """ type: Literal["response.cancel"] """The event type, must be `response.cancel`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" response_id: Optional[str] = None """ A specific response ID to cancel - if not provided, will cancel an in-progress response in the default conversation. """ ================================================ FILE: src/openai/types/realtime/response_cancel_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ResponseCancelEventParam"] class ResponseCancelEventParam(TypedDict, total=False): """Send this event to cancel an in-progress response. The server will respond with a `response.done` event with a status of `response.status=cancelled`. If there is no response to cancel, the server will respond with an error. It's safe to call `response.cancel` even if no response is in progress, an error will be returned the session will remain unaffected. """ type: Required[Literal["response.cancel"]] """The event type, must be `response.cancel`.""" event_id: str """Optional client-generated ID used to identify this event.""" response_id: str """ A specific response ID to cancel - if not provided, will cancel an in-progress response in the default conversation. """ ================================================ FILE: src/openai/types/realtime/response_content_part_added_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseContentPartAddedEvent", "Part"] class Part(BaseModel): """The content part that was added.""" audio: Optional[str] = None """Base64-encoded audio data (if type is "audio").""" text: Optional[str] = None """The text content (if type is "text").""" transcript: Optional[str] = None """The transcript of the audio (if type is "audio").""" type: Optional[Literal["text", "audio"]] = None """The content type ("text", "audio").""" class ResponseContentPartAddedEvent(BaseModel): """ Returned when a new content part is added to an assistant message item during response generation. """ content_index: int """The index of the content part in the item's content array.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item to which the content part was added.""" output_index: int """The index of the output item in the response.""" part: Part """The content part that was added.""" response_id: str """The ID of the response.""" type: Literal["response.content_part.added"] """The event type, must be `response.content_part.added`.""" ================================================ FILE: src/openai/types/realtime/response_content_part_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseContentPartDoneEvent", "Part"] class Part(BaseModel): """The content part that is done.""" audio: Optional[str] = None """Base64-encoded audio data (if type is "audio").""" text: Optional[str] = None """The text content (if type is "text").""" transcript: Optional[str] = None """The transcript of the audio (if type is "audio").""" type: Optional[Literal["text", "audio"]] = None """The content type ("text", "audio").""" class ResponseContentPartDoneEvent(BaseModel): """ Returned when a content part is done streaming in an assistant message item. Also emitted when a Response is interrupted, incomplete, or cancelled. """ content_index: int """The index of the content part in the item's content array.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item.""" output_index: int """The index of the output item in the response.""" part: Part """The content part that is done.""" response_id: str """The ID of the response.""" type: Literal["response.content_part.done"] """The event type, must be `response.content_part.done`.""" ================================================ FILE: src/openai/types/realtime/response_create_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel from .realtime_response_create_params import RealtimeResponseCreateParams __all__ = ["ResponseCreateEvent"] class ResponseCreateEvent(BaseModel): """ This event instructs the server to create a Response, which means triggering model inference. When in Server VAD mode, the server will create Responses automatically. A Response will include at least one Item, and may have two, in which case the second will be a function call. These Items will be appended to the conversation history by default. The server will respond with a `response.created` event, events for Items and content created, and finally a `response.done` event to indicate the Response is complete. The `response.create` event includes inference configuration like `instructions` and `tools`. If these are set, they will override the Session's configuration for this Response only. Responses can be created out-of-band of the default Conversation, meaning that they can have arbitrary input, and it's possible to disable writing the output to the Conversation. Only one Response can write to the default Conversation at a time, but otherwise multiple Responses can be created in parallel. The `metadata` field is a good way to disambiguate multiple simultaneous Responses. Clients can set `conversation` to `none` to create a Response that does not write to the default Conversation. Arbitrary input can be provided with the `input` field, which is an array accepting raw Items and references to existing Items. """ type: Literal["response.create"] """The event type, must be `response.create`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event.""" response: Optional[RealtimeResponseCreateParams] = None """Create a new Realtime response with these parameters""" ================================================ FILE: src/openai/types/realtime/response_create_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict from .realtime_response_create_params_param import RealtimeResponseCreateParamsParam __all__ = ["ResponseCreateEventParam"] class ResponseCreateEventParam(TypedDict, total=False): """ This event instructs the server to create a Response, which means triggering model inference. When in Server VAD mode, the server will create Responses automatically. A Response will include at least one Item, and may have two, in which case the second will be a function call. These Items will be appended to the conversation history by default. The server will respond with a `response.created` event, events for Items and content created, and finally a `response.done` event to indicate the Response is complete. The `response.create` event includes inference configuration like `instructions` and `tools`. If these are set, they will override the Session's configuration for this Response only. Responses can be created out-of-band of the default Conversation, meaning that they can have arbitrary input, and it's possible to disable writing the output to the Conversation. Only one Response can write to the default Conversation at a time, but otherwise multiple Responses can be created in parallel. The `metadata` field is a good way to disambiguate multiple simultaneous Responses. Clients can set `conversation` to `none` to create a Response that does not write to the default Conversation. Arbitrary input can be provided with the `input` field, which is an array accepting raw Items and references to existing Items. """ type: Required[Literal["response.create"]] """The event type, must be `response.create`.""" event_id: str """Optional client-generated ID used to identify this event.""" response: RealtimeResponseCreateParamsParam """Create a new Realtime response with these parameters""" ================================================ FILE: src/openai/types/realtime/response_created_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel from .realtime_response import RealtimeResponse __all__ = ["ResponseCreatedEvent"] class ResponseCreatedEvent(BaseModel): """Returned when a new Response is created. The first event of response creation, where the response is in an initial state of `in_progress`. """ event_id: str """The unique ID of the server event.""" response: RealtimeResponse """The response resource.""" type: Literal["response.created"] """The event type, must be `response.created`.""" ================================================ FILE: src/openai/types/realtime/response_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel from .realtime_response import RealtimeResponse __all__ = ["ResponseDoneEvent"] class ResponseDoneEvent(BaseModel): """Returned when a Response is done streaming. Always emitted, no matter the final state. The Response object included in the `response.done` event will include all output Items in the Response but will omit the raw audio data. Clients should check the `status` field of the Response to determine if it was successful (`completed`) or if there was another outcome: `cancelled`, `failed`, or `incomplete`. A response will contain all output items that were generated during the response, excluding any audio content. """ event_id: str """The unique ID of the server event.""" response: RealtimeResponse """The response resource.""" type: Literal["response.done"] """The event type, must be `response.done`.""" ================================================ FILE: src/openai/types/realtime/response_function_call_arguments_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseFunctionCallArgumentsDeltaEvent"] class ResponseFunctionCallArgumentsDeltaEvent(BaseModel): """Returned when the model-generated function call arguments are updated.""" call_id: str """The ID of the function call.""" delta: str """The arguments delta as a JSON string.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the function call item.""" output_index: int """The index of the output item in the response.""" response_id: str """The ID of the response.""" type: Literal["response.function_call_arguments.delta"] """The event type, must be `response.function_call_arguments.delta`.""" ================================================ FILE: src/openai/types/realtime/response_function_call_arguments_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseFunctionCallArgumentsDoneEvent"] class ResponseFunctionCallArgumentsDoneEvent(BaseModel): """ Returned when the model-generated function call arguments are done streaming. Also emitted when a Response is interrupted, incomplete, or cancelled. """ arguments: str """The final arguments as a JSON string.""" call_id: str """The ID of the function call.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the function call item.""" name: str """The name of the function that was called.""" output_index: int """The index of the output item in the response.""" response_id: str """The ID of the response.""" type: Literal["response.function_call_arguments.done"] """The event type, must be `response.function_call_arguments.done`.""" ================================================ FILE: src/openai/types/realtime/response_mcp_call_arguments_delta.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseMcpCallArgumentsDelta"] class ResponseMcpCallArgumentsDelta(BaseModel): """Returned when MCP tool call arguments are updated during response generation.""" delta: str """The JSON-encoded arguments delta.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the MCP tool call item.""" output_index: int """The index of the output item in the response.""" response_id: str """The ID of the response.""" type: Literal["response.mcp_call_arguments.delta"] """The event type, must be `response.mcp_call_arguments.delta`.""" obfuscation: Optional[str] = None """If present, indicates the delta text was obfuscated.""" ================================================ FILE: src/openai/types/realtime/response_mcp_call_arguments_done.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseMcpCallArgumentsDone"] class ResponseMcpCallArgumentsDone(BaseModel): """Returned when MCP tool call arguments are finalized during response generation.""" arguments: str """The final JSON-encoded arguments string.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the MCP tool call item.""" output_index: int """The index of the output item in the response.""" response_id: str """The ID of the response.""" type: Literal["response.mcp_call_arguments.done"] """The event type, must be `response.mcp_call_arguments.done`.""" ================================================ FILE: src/openai/types/realtime/response_mcp_call_completed.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseMcpCallCompleted"] class ResponseMcpCallCompleted(BaseModel): """Returned when an MCP tool call has completed successfully.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the MCP tool call item.""" output_index: int """The index of the output item in the response.""" type: Literal["response.mcp_call.completed"] """The event type, must be `response.mcp_call.completed`.""" ================================================ FILE: src/openai/types/realtime/response_mcp_call_failed.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseMcpCallFailed"] class ResponseMcpCallFailed(BaseModel): """Returned when an MCP tool call has failed.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the MCP tool call item.""" output_index: int """The index of the output item in the response.""" type: Literal["response.mcp_call.failed"] """The event type, must be `response.mcp_call.failed`.""" ================================================ FILE: src/openai/types/realtime/response_mcp_call_in_progress.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseMcpCallInProgress"] class ResponseMcpCallInProgress(BaseModel): """Returned when an MCP tool call has started and is in progress.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the MCP tool call item.""" output_index: int """The index of the output item in the response.""" type: Literal["response.mcp_call.in_progress"] """The event type, must be `response.mcp_call.in_progress`.""" ================================================ FILE: src/openai/types/realtime/response_output_item_added_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel from .conversation_item import ConversationItem __all__ = ["ResponseOutputItemAddedEvent"] class ResponseOutputItemAddedEvent(BaseModel): """Returned when a new Item is created during Response generation.""" event_id: str """The unique ID of the server event.""" item: ConversationItem """A single item within a Realtime conversation.""" output_index: int """The index of the output item in the Response.""" response_id: str """The ID of the Response to which the item belongs.""" type: Literal["response.output_item.added"] """The event type, must be `response.output_item.added`.""" ================================================ FILE: src/openai/types/realtime/response_output_item_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel from .conversation_item import ConversationItem __all__ = ["ResponseOutputItemDoneEvent"] class ResponseOutputItemDoneEvent(BaseModel): """Returned when an Item is done streaming. Also emitted when a Response is interrupted, incomplete, or cancelled. """ event_id: str """The unique ID of the server event.""" item: ConversationItem """A single item within a Realtime conversation.""" output_index: int """The index of the output item in the Response.""" response_id: str """The ID of the Response to which the item belongs.""" type: Literal["response.output_item.done"] """The event type, must be `response.output_item.done`.""" ================================================ FILE: src/openai/types/realtime/response_text_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseTextDeltaEvent"] class ResponseTextDeltaEvent(BaseModel): """Returned when the text value of an "output_text" content part is updated.""" content_index: int """The index of the content part in the item's content array.""" delta: str """The text delta.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item.""" output_index: int """The index of the output item in the response.""" response_id: str """The ID of the response.""" type: Literal["response.output_text.delta"] """The event type, must be `response.output_text.delta`.""" ================================================ FILE: src/openai/types/realtime/response_text_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseTextDoneEvent"] class ResponseTextDoneEvent(BaseModel): """Returned when the text value of an "output_text" content part is done streaming. Also emitted when a Response is interrupted, incomplete, or cancelled. """ content_index: int """The index of the content part in the item's content array.""" event_id: str """The unique ID of the server event.""" item_id: str """The ID of the item.""" output_index: int """The index of the output item in the response.""" response_id: str """The ID of the response.""" text: str """The final text content.""" type: Literal["response.output_text.done"] """The event type, must be `response.output_text.done`.""" ================================================ FILE: src/openai/types/realtime/session_created_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Literal, TypeAlias from ..._models import BaseModel from .realtime_session_create_request import RealtimeSessionCreateRequest from .realtime_transcription_session_create_request import RealtimeTranscriptionSessionCreateRequest __all__ = ["SessionCreatedEvent", "Session"] Session: TypeAlias = Union[RealtimeSessionCreateRequest, RealtimeTranscriptionSessionCreateRequest] class SessionCreatedEvent(BaseModel): """Returned when a Session is created. Emitted automatically when a new connection is established as the first server event. This event will contain the default Session configuration. """ event_id: str """The unique ID of the server event.""" session: Session """The session configuration.""" type: Literal["session.created"] """The event type, must be `session.created`.""" ================================================ FILE: src/openai/types/realtime/session_update_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import Literal, TypeAlias from ..._models import BaseModel from .realtime_session_create_request import RealtimeSessionCreateRequest from .realtime_transcription_session_create_request import RealtimeTranscriptionSessionCreateRequest __all__ = ["SessionUpdateEvent", "Session"] Session: TypeAlias = Union[RealtimeSessionCreateRequest, RealtimeTranscriptionSessionCreateRequest] class SessionUpdateEvent(BaseModel): """ Send this event to update the session’s configuration. The client may send this event at any time to update any field except for `voice` and `model`. `voice` can be updated only if there have been no other audio outputs yet. When the server receives a `session.update`, it will respond with a `session.updated` event showing the full, effective configuration. Only the fields that are present in the `session.update` are updated. To clear a field like `instructions`, pass an empty string. To clear a field like `tools`, pass an empty array. To clear a field like `turn_detection`, pass `null`. """ session: Session """Update the Realtime session. Choose either a realtime session or a transcription session. """ type: Literal["session.update"] """The event type, must be `session.update`.""" event_id: Optional[str] = None """Optional client-generated ID used to identify this event. This is an arbitrary string that a client may assign. It will be passed back if there is an error with the event, but the corresponding `session.updated` event will not include it. """ ================================================ FILE: src/openai/types/realtime/session_update_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, Required, TypeAlias, TypedDict from .realtime_session_create_request_param import RealtimeSessionCreateRequestParam from .realtime_transcription_session_create_request_param import RealtimeTranscriptionSessionCreateRequestParam __all__ = ["SessionUpdateEventParam", "Session"] Session: TypeAlias = Union[RealtimeSessionCreateRequestParam, RealtimeTranscriptionSessionCreateRequestParam] class SessionUpdateEventParam(TypedDict, total=False): """ Send this event to update the session’s configuration. The client may send this event at any time to update any field except for `voice` and `model`. `voice` can be updated only if there have been no other audio outputs yet. When the server receives a `session.update`, it will respond with a `session.updated` event showing the full, effective configuration. Only the fields that are present in the `session.update` are updated. To clear a field like `instructions`, pass an empty string. To clear a field like `tools`, pass an empty array. To clear a field like `turn_detection`, pass `null`. """ session: Required[Session] """Update the Realtime session. Choose either a realtime session or a transcription session. """ type: Required[Literal["session.update"]] """The event type, must be `session.update`.""" event_id: str """Optional client-generated ID used to identify this event. This is an arbitrary string that a client may assign. It will be passed back if there is an error with the event, but the corresponding `session.updated` event will not include it. """ ================================================ FILE: src/openai/types/realtime/session_updated_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Literal, TypeAlias from ..._models import BaseModel from .realtime_session_create_request import RealtimeSessionCreateRequest from .realtime_transcription_session_create_request import RealtimeTranscriptionSessionCreateRequest __all__ = ["SessionUpdatedEvent", "Session"] Session: TypeAlias = Union[RealtimeSessionCreateRequest, RealtimeTranscriptionSessionCreateRequest] class SessionUpdatedEvent(BaseModel): """ Returned when a session is updated with a `session.update` event, unless there is an error. """ event_id: str """The unique ID of the server event.""" session: Session """The session configuration.""" type: Literal["session.updated"] """The event type, must be `session.updated`.""" ================================================ FILE: src/openai/types/responses/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .tool import Tool as Tool from .response import Response as Response from .tool_param import ToolParam as ToolParam from .custom_tool import CustomTool as CustomTool from .local_skill import LocalSkill as LocalSkill from .inline_skill import InlineSkill as InlineSkill from .computer_tool import ComputerTool as ComputerTool from .function_tool import FunctionTool as FunctionTool from .response_item import ResponseItem as ResponseItem from .container_auto import ContainerAuto as ContainerAuto from .namespace_tool import NamespaceTool as NamespaceTool from .response_error import ResponseError as ResponseError from .response_input import ResponseInput as ResponseInput from .response_usage import ResponseUsage as ResponseUsage from .computer_action import ComputerAction as ComputerAction from .parsed_response import ( ParsedContent as ParsedContent, ParsedResponse as ParsedResponse, ParsedResponseOutputItem as ParsedResponseOutputItem, ParsedResponseOutputText as ParsedResponseOutputText, ParsedResponseOutputMessage as ParsedResponseOutputMessage, ParsedResponseFunctionToolCall as ParsedResponseFunctionToolCall, ) from .response_prompt import ResponsePrompt as ResponsePrompt from .response_status import ResponseStatus as ResponseStatus from .skill_reference import SkillReference as SkillReference from .tool_choice_mcp import ToolChoiceMcp as ToolChoiceMcp from .web_search_tool import WebSearchTool as WebSearchTool from .apply_patch_tool import ApplyPatchTool as ApplyPatchTool from .file_search_tool import FileSearchTool as FileSearchTool from .tool_search_tool import ToolSearchTool as ToolSearchTool from .custom_tool_param import CustomToolParam as CustomToolParam from .local_environment import LocalEnvironment as LocalEnvironment from .local_skill_param import LocalSkillParam as LocalSkillParam from .tool_choice_shell import ToolChoiceShell as ToolChoiceShell from .tool_choice_types import ToolChoiceTypes as ToolChoiceTypes from .compacted_response import CompactedResponse as CompactedResponse from .easy_input_message import EasyInputMessage as EasyInputMessage from .inline_skill_param import InlineSkillParam as InlineSkillParam from .response_item_list import ResponseItemList as ResponseItemList from .tool_choice_custom import ToolChoiceCustom as ToolChoiceCustom from .computer_tool_param import ComputerToolParam as ComputerToolParam from .container_reference import ContainerReference as ContainerReference from .function_shell_tool import FunctionShellTool as FunctionShellTool from .function_tool_param import FunctionToolParam as FunctionToolParam from .inline_skill_source import InlineSkillSource as InlineSkillSource from .response_includable import ResponseIncludable as ResponseIncludable from .response_input_file import ResponseInputFile as ResponseInputFile from .response_input_item import ResponseInputItem as ResponseInputItem from .response_input_text import ResponseInputText as ResponseInputText from .tool_choice_allowed import ToolChoiceAllowed as ToolChoiceAllowed from .tool_choice_options import ToolChoiceOptions as ToolChoiceOptions from .computer_action_list import ComputerActionList as ComputerActionList from .container_auto_param import ContainerAutoParam as ContainerAutoParam from .namespace_tool_param import NamespaceToolParam as NamespaceToolParam from .response_error_event import ResponseErrorEvent as ResponseErrorEvent from .response_input_audio import ResponseInputAudio as ResponseInputAudio from .response_input_image import ResponseInputImage as ResponseInputImage from .response_input_param import ResponseInputParam as ResponseInputParam from .response_output_item import ResponseOutputItem as ResponseOutputItem from .response_output_text import ResponseOutputText as ResponseOutputText from .response_text_config import ResponseTextConfig as ResponseTextConfig from .tool_choice_function import ToolChoiceFunction as ToolChoiceFunction from .computer_action_param import ComputerActionParam as ComputerActionParam from .response_failed_event import ResponseFailedEvent as ResponseFailedEvent from .response_prompt_param import ResponsePromptParam as ResponsePromptParam from .response_queued_event import ResponseQueuedEvent as ResponseQueuedEvent from .response_stream_event import ResponseStreamEvent as ResponseStreamEvent from .skill_reference_param import SkillReferenceParam as SkillReferenceParam from .tool_choice_mcp_param import ToolChoiceMcpParam as ToolChoiceMcpParam from .web_search_tool_param import WebSearchToolParam as WebSearchToolParam from .apply_patch_tool_param import ApplyPatchToolParam as ApplyPatchToolParam from .file_search_tool_param import FileSearchToolParam as FileSearchToolParam from .input_item_list_params import InputItemListParams as InputItemListParams from .response_create_params import ResponseCreateParams as ResponseCreateParams from .response_created_event import ResponseCreatedEvent as ResponseCreatedEvent from .response_input_content import ResponseInputContent as ResponseInputContent from .responses_client_event import ResponsesClientEvent as ResponsesClientEvent from .responses_server_event import ResponsesServerEvent as ResponsesServerEvent from .tool_search_tool_param import ToolSearchToolParam as ToolSearchToolParam from .local_environment_param import LocalEnvironmentParam as LocalEnvironmentParam from .response_compact_params import ResponseCompactParams as ResponseCompactParams from .response_output_message import ResponseOutputMessage as ResponseOutputMessage from .response_output_refusal import ResponseOutputRefusal as ResponseOutputRefusal from .response_reasoning_item import ResponseReasoningItem as ResponseReasoningItem from .tool_choice_apply_patch import ToolChoiceApplyPatch as ToolChoiceApplyPatch from .tool_choice_shell_param import ToolChoiceShellParam as ToolChoiceShellParam from .tool_choice_types_param import ToolChoiceTypesParam as ToolChoiceTypesParam from .web_search_preview_tool import WebSearchPreviewTool as WebSearchPreviewTool from .easy_input_message_param import EasyInputMessageParam as EasyInputMessageParam from .input_token_count_params import InputTokenCountParams as InputTokenCountParams from .response_compaction_item import ResponseCompactionItem as ResponseCompactionItem from .response_completed_event import ResponseCompletedEvent as ResponseCompletedEvent from .response_retrieve_params import ResponseRetrieveParams as ResponseRetrieveParams from .response_text_done_event import ResponseTextDoneEvent as ResponseTextDoneEvent from .tool_choice_custom_param import ToolChoiceCustomParam as ToolChoiceCustomParam from .computer_use_preview_tool import ComputerUsePreviewTool as ComputerUsePreviewTool from .container_reference_param import ContainerReferenceParam as ContainerReferenceParam from .function_shell_tool_param import FunctionShellToolParam as FunctionShellToolParam from .inline_skill_source_param import InlineSkillSourceParam as InlineSkillSourceParam from .response_audio_done_event import ResponseAudioDoneEvent as ResponseAudioDoneEvent from .response_custom_tool_call import ResponseCustomToolCall as ResponseCustomToolCall from .response_incomplete_event import ResponseIncompleteEvent as ResponseIncompleteEvent from .response_input_file_param import ResponseInputFileParam as ResponseInputFileParam from .response_input_item_param import ResponseInputItemParam as ResponseInputItemParam from .response_input_text_param import ResponseInputTextParam as ResponseInputTextParam from .response_text_delta_event import ResponseTextDeltaEvent as ResponseTextDeltaEvent from .response_tool_search_call import ResponseToolSearchCall as ResponseToolSearchCall from .tool_choice_allowed_param import ToolChoiceAllowedParam as ToolChoiceAllowedParam from .computer_action_list_param import ComputerActionListParam as ComputerActionListParam from .input_token_count_response import InputTokenCountResponse as InputTokenCountResponse from .response_audio_delta_event import ResponseAudioDeltaEvent as ResponseAudioDeltaEvent from .response_in_progress_event import ResponseInProgressEvent as ResponseInProgressEvent from .response_input_audio_param import ResponseInputAudioParam as ResponseInputAudioParam from .response_input_image_param import ResponseInputImageParam as ResponseInputImageParam from .response_local_environment import ResponseLocalEnvironment as ResponseLocalEnvironment from .response_output_text_param import ResponseOutputTextParam as ResponseOutputTextParam from .response_text_config_param import ResponseTextConfigParam as ResponseTextConfigParam from .tool_choice_function_param import ToolChoiceFunctionParam as ToolChoiceFunctionParam from .response_computer_tool_call import ResponseComputerToolCall as ResponseComputerToolCall from .response_conversation_param import ResponseConversationParam as ResponseConversationParam from .response_format_text_config import ResponseFormatTextConfig as ResponseFormatTextConfig from .response_function_tool_call import ResponseFunctionToolCall as ResponseFunctionToolCall from .response_input_file_content import ResponseInputFileContent as ResponseInputFileContent from .response_input_message_item import ResponseInputMessageItem as ResponseInputMessageItem from .response_input_text_content import ResponseInputTextContent as ResponseInputTextContent from .response_refusal_done_event import ResponseRefusalDoneEvent as ResponseRefusalDoneEvent from .response_container_reference import ResponseContainerReference as ResponseContainerReference from .response_function_web_search import ResponseFunctionWebSearch as ResponseFunctionWebSearch from .response_input_content_param import ResponseInputContentParam as ResponseInputContentParam from .response_input_image_content import ResponseInputImageContent as ResponseInputImageContent from .response_refusal_delta_event import ResponseRefusalDeltaEvent as ResponseRefusalDeltaEvent from .responses_client_event_param import ResponsesClientEventParam as ResponsesClientEventParam from .response_output_message_param import ResponseOutputMessageParam as ResponseOutputMessageParam from .response_output_refusal_param import ResponseOutputRefusalParam as ResponseOutputRefusalParam from .response_reasoning_item_param import ResponseReasoningItemParam as ResponseReasoningItemParam from .tool_choice_apply_patch_param import ToolChoiceApplyPatchParam as ToolChoiceApplyPatchParam from .web_search_preview_tool_param import WebSearchPreviewToolParam as WebSearchPreviewToolParam from .response_apply_patch_tool_call import ResponseApplyPatchToolCall as ResponseApplyPatchToolCall from .response_compaction_item_param import ResponseCompactionItemParam as ResponseCompactionItemParam from .response_file_search_tool_call import ResponseFileSearchToolCall as ResponseFileSearchToolCall from .response_mcp_call_failed_event import ResponseMcpCallFailedEvent as ResponseMcpCallFailedEvent from .computer_use_preview_tool_param import ComputerUsePreviewToolParam as ComputerUsePreviewToolParam from .response_custom_tool_call_param import ResponseCustomToolCallParam as ResponseCustomToolCallParam from .response_output_item_done_event import ResponseOutputItemDoneEvent as ResponseOutputItemDoneEvent from .response_content_part_done_event import ResponseContentPartDoneEvent as ResponseContentPartDoneEvent from .response_custom_tool_call_output import ResponseCustomToolCallOutput as ResponseCustomToolCallOutput from .response_function_tool_call_item import ResponseFunctionToolCallItem as ResponseFunctionToolCallItem from .response_output_item_added_event import ResponseOutputItemAddedEvent as ResponseOutputItemAddedEvent from .response_tool_search_output_item import ResponseToolSearchOutputItem as ResponseToolSearchOutputItem from .container_network_policy_disabled import ContainerNetworkPolicyDisabled as ContainerNetworkPolicyDisabled from .response_computer_tool_call_param import ResponseComputerToolCallParam as ResponseComputerToolCallParam from .response_content_part_added_event import ResponseContentPartAddedEvent as ResponseContentPartAddedEvent from .response_conversation_param_param import ResponseConversationParamParam as ResponseConversationParamParam from .response_format_text_config_param import ResponseFormatTextConfigParam as ResponseFormatTextConfigParam from .response_function_shell_tool_call import ResponseFunctionShellToolCall as ResponseFunctionShellToolCall from .response_function_tool_call_param import ResponseFunctionToolCallParam as ResponseFunctionToolCallParam from .response_input_file_content_param import ResponseInputFileContentParam as ResponseInputFileContentParam from .response_input_text_content_param import ResponseInputTextContentParam as ResponseInputTextContentParam from .response_mcp_call_completed_event import ResponseMcpCallCompletedEvent as ResponseMcpCallCompletedEvent from .container_network_policy_allowlist import ContainerNetworkPolicyAllowlist as ContainerNetworkPolicyAllowlist from .response_function_call_output_item import ResponseFunctionCallOutputItem as ResponseFunctionCallOutputItem from .response_function_web_search_param import ResponseFunctionWebSearchParam as ResponseFunctionWebSearchParam from .response_input_image_content_param import ResponseInputImageContentParam as ResponseInputImageContentParam from .response_reasoning_text_done_event import ResponseReasoningTextDoneEvent as ResponseReasoningTextDoneEvent from .response_code_interpreter_tool_call import ResponseCodeInterpreterToolCall as ResponseCodeInterpreterToolCall from .response_input_message_content_list import ResponseInputMessageContentList as ResponseInputMessageContentList from .response_mcp_call_in_progress_event import ResponseMcpCallInProgressEvent as ResponseMcpCallInProgressEvent from .response_reasoning_text_delta_event import ResponseReasoningTextDeltaEvent as ResponseReasoningTextDeltaEvent from .response_audio_transcript_done_event import ResponseAudioTranscriptDoneEvent as ResponseAudioTranscriptDoneEvent from .response_compaction_item_param_param import ResponseCompactionItemParamParam as ResponseCompactionItemParamParam from .response_file_search_tool_call_param import ResponseFileSearchToolCallParam as ResponseFileSearchToolCallParam from .response_mcp_list_tools_failed_event import ResponseMcpListToolsFailedEvent as ResponseMcpListToolsFailedEvent from .response_apply_patch_tool_call_output import ResponseApplyPatchToolCallOutput as ResponseApplyPatchToolCallOutput from .response_audio_transcript_delta_event import ( ResponseAudioTranscriptDeltaEvent as ResponseAudioTranscriptDeltaEvent, ) from .container_network_policy_domain_secret import ( ContainerNetworkPolicyDomainSecret as ContainerNetworkPolicyDomainSecret, ) from .response_custom_tool_call_output_param import ( ResponseCustomToolCallOutputParam as ResponseCustomToolCallOutputParam, ) from .response_mcp_call_arguments_done_event import ( ResponseMcpCallArgumentsDoneEvent as ResponseMcpCallArgumentsDoneEvent, ) from .response_tool_search_output_item_param import ( ResponseToolSearchOutputItemParam as ResponseToolSearchOutputItemParam, ) from .container_network_policy_disabled_param import ( ContainerNetworkPolicyDisabledParam as ContainerNetworkPolicyDisabledParam, ) from .response_computer_tool_call_output_item import ( ResponseComputerToolCallOutputItem as ResponseComputerToolCallOutputItem, ) from .response_format_text_json_schema_config import ( ResponseFormatTextJSONSchemaConfig as ResponseFormatTextJSONSchemaConfig, ) from .response_function_call_output_item_list import ( ResponseFunctionCallOutputItemList as ResponseFunctionCallOutputItemList, ) from .response_function_tool_call_output_item import ( ResponseFunctionToolCallOutputItem as ResponseFunctionToolCallOutputItem, ) from .response_image_gen_call_completed_event import ( ResponseImageGenCallCompletedEvent as ResponseImageGenCallCompletedEvent, ) from .response_mcp_call_arguments_delta_event import ( ResponseMcpCallArgumentsDeltaEvent as ResponseMcpCallArgumentsDeltaEvent, ) from .response_mcp_list_tools_completed_event import ( ResponseMcpListToolsCompletedEvent as ResponseMcpListToolsCompletedEvent, ) from .container_network_policy_allowlist_param import ( ContainerNetworkPolicyAllowlistParam as ContainerNetworkPolicyAllowlistParam, ) from .response_function_call_output_item_param import ( ResponseFunctionCallOutputItemParam as ResponseFunctionCallOutputItemParam, ) from .response_function_shell_tool_call_output import ( ResponseFunctionShellToolCallOutput as ResponseFunctionShellToolCallOutput, ) from .response_image_gen_call_generating_event import ( ResponseImageGenCallGeneratingEvent as ResponseImageGenCallGeneratingEvent, ) from .response_web_search_call_completed_event import ( ResponseWebSearchCallCompletedEvent as ResponseWebSearchCallCompletedEvent, ) from .response_web_search_call_searching_event import ( ResponseWebSearchCallSearchingEvent as ResponseWebSearchCallSearchingEvent, ) from .response_code_interpreter_tool_call_param import ( ResponseCodeInterpreterToolCallParam as ResponseCodeInterpreterToolCallParam, ) from .response_file_search_call_completed_event import ( ResponseFileSearchCallCompletedEvent as ResponseFileSearchCallCompletedEvent, ) from .response_file_search_call_searching_event import ( ResponseFileSearchCallSearchingEvent as ResponseFileSearchCallSearchingEvent, ) from .response_image_gen_call_in_progress_event import ( ResponseImageGenCallInProgressEvent as ResponseImageGenCallInProgressEvent, ) from .response_input_message_content_list_param import ( ResponseInputMessageContentListParam as ResponseInputMessageContentListParam, ) from .response_mcp_list_tools_in_progress_event import ( ResponseMcpListToolsInProgressEvent as ResponseMcpListToolsInProgressEvent, ) from .response_custom_tool_call_input_done_event import ( ResponseCustomToolCallInputDoneEvent as ResponseCustomToolCallInputDoneEvent, ) from .response_reasoning_summary_part_done_event import ( ResponseReasoningSummaryPartDoneEvent as ResponseReasoningSummaryPartDoneEvent, ) from .response_reasoning_summary_text_done_event import ( ResponseReasoningSummaryTextDoneEvent as ResponseReasoningSummaryTextDoneEvent, ) from .response_web_search_call_in_progress_event import ( ResponseWebSearchCallInProgressEvent as ResponseWebSearchCallInProgressEvent, ) from .response_custom_tool_call_input_delta_event import ( ResponseCustomToolCallInputDeltaEvent as ResponseCustomToolCallInputDeltaEvent, ) from .response_file_search_call_in_progress_event import ( ResponseFileSearchCallInProgressEvent as ResponseFileSearchCallInProgressEvent, ) from .response_function_call_arguments_done_event import ( ResponseFunctionCallArgumentsDoneEvent as ResponseFunctionCallArgumentsDoneEvent, ) from .response_function_shell_call_output_content import ( ResponseFunctionShellCallOutputContent as ResponseFunctionShellCallOutputContent, ) from .response_image_gen_call_partial_image_event import ( ResponseImageGenCallPartialImageEvent as ResponseImageGenCallPartialImageEvent, ) from .response_output_text_annotation_added_event import ( ResponseOutputTextAnnotationAddedEvent as ResponseOutputTextAnnotationAddedEvent, ) from .response_reasoning_summary_part_added_event import ( ResponseReasoningSummaryPartAddedEvent as ResponseReasoningSummaryPartAddedEvent, ) from .response_reasoning_summary_text_delta_event import ( ResponseReasoningSummaryTextDeltaEvent as ResponseReasoningSummaryTextDeltaEvent, ) from .container_network_policy_domain_secret_param import ( ContainerNetworkPolicyDomainSecretParam as ContainerNetworkPolicyDomainSecretParam, ) from .response_function_call_arguments_delta_event import ( ResponseFunctionCallArgumentsDeltaEvent as ResponseFunctionCallArgumentsDeltaEvent, ) from .response_tool_search_output_item_param_param import ( ResponseToolSearchOutputItemParamParam as ResponseToolSearchOutputItemParamParam, ) from .response_computer_tool_call_output_screenshot import ( ResponseComputerToolCallOutputScreenshot as ResponseComputerToolCallOutputScreenshot, ) from .response_format_text_json_schema_config_param import ( ResponseFormatTextJSONSchemaConfigParam as ResponseFormatTextJSONSchemaConfigParam, ) from .response_function_call_output_item_list_param import ( ResponseFunctionCallOutputItemListParam as ResponseFunctionCallOutputItemListParam, ) from .response_code_interpreter_call_code_done_event import ( ResponseCodeInterpreterCallCodeDoneEvent as ResponseCodeInterpreterCallCodeDoneEvent, ) from .response_code_interpreter_call_completed_event import ( ResponseCodeInterpreterCallCompletedEvent as ResponseCodeInterpreterCallCompletedEvent, ) from .response_code_interpreter_call_code_delta_event import ( ResponseCodeInterpreterCallCodeDeltaEvent as ResponseCodeInterpreterCallCodeDeltaEvent, ) from .response_code_interpreter_call_in_progress_event import ( ResponseCodeInterpreterCallInProgressEvent as ResponseCodeInterpreterCallInProgressEvent, ) from .response_code_interpreter_call_interpreting_event import ( ResponseCodeInterpreterCallInterpretingEvent as ResponseCodeInterpreterCallInterpretingEvent, ) from .response_function_shell_call_output_content_param import ( ResponseFunctionShellCallOutputContentParam as ResponseFunctionShellCallOutputContentParam, ) from .response_computer_tool_call_output_screenshot_param import ( ResponseComputerToolCallOutputScreenshotParam as ResponseComputerToolCallOutputScreenshotParam, ) ================================================ FILE: src/openai/types/responses/apply_patch_tool.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ApplyPatchTool"] class ApplyPatchTool(BaseModel): """Allows the assistant to create, delete, or update files using unified diffs.""" type: Literal["apply_patch"] """The type of the tool. Always `apply_patch`.""" ================================================ FILE: src/openai/types/responses/apply_patch_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ApplyPatchToolParam"] class ApplyPatchToolParam(TypedDict, total=False): """Allows the assistant to create, delete, or update files using unified diffs.""" type: Required[Literal["apply_patch"]] """The type of the tool. Always `apply_patch`.""" ================================================ FILE: src/openai/types/responses/compacted_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List from typing_extensions import Literal from ..._models import BaseModel from .response_usage import ResponseUsage from .response_output_item import ResponseOutputItem __all__ = ["CompactedResponse"] class CompactedResponse(BaseModel): id: str """The unique identifier for the compacted response.""" created_at: int """Unix timestamp (in seconds) when the compacted conversation was created.""" object: Literal["response.compaction"] """The object type. Always `response.compaction`.""" output: List[ResponseOutputItem] """The compacted list of output items. This is a list of all user messages, followed by a single compaction item. """ usage: ResponseUsage """ Token accounting for the compaction pass, including cached, reasoning, and total tokens. """ ================================================ FILE: src/openai/types/responses/computer_action.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = [ "ComputerAction", "Click", "DoubleClick", "Drag", "DragPath", "Keypress", "Move", "Screenshot", "Scroll", "Type", "Wait", ] class Click(BaseModel): """A click action.""" button: Literal["left", "right", "wheel", "back", "forward"] """Indicates which mouse button was pressed during the click. One of `left`, `right`, `wheel`, `back`, or `forward`. """ type: Literal["click"] """Specifies the event type. For a click action, this property is always `click`.""" x: int """The x-coordinate where the click occurred.""" y: int """The y-coordinate where the click occurred.""" class DoubleClick(BaseModel): """A double click action.""" type: Literal["double_click"] """Specifies the event type. For a double click action, this property is always set to `double_click`. """ x: int """The x-coordinate where the double click occurred.""" y: int """The y-coordinate where the double click occurred.""" class DragPath(BaseModel): """An x/y coordinate pair, e.g. `{ x: 100, y: 200 }`.""" x: int """The x-coordinate.""" y: int """The y-coordinate.""" class Drag(BaseModel): """A drag action.""" path: List[DragPath] """An array of coordinates representing the path of the drag action. Coordinates will appear as an array of objects, eg ``` [ { x: 100, y: 200 }, { x: 200, y: 300 } ] ``` """ type: Literal["drag"] """Specifies the event type. For a drag action, this property is always set to `drag`. """ class Keypress(BaseModel): """A collection of keypresses the model would like to perform.""" keys: List[str] """The combination of keys the model is requesting to be pressed. This is an array of strings, each representing a key. """ type: Literal["keypress"] """Specifies the event type. For a keypress action, this property is always set to `keypress`. """ class Move(BaseModel): """A mouse move action.""" type: Literal["move"] """Specifies the event type. For a move action, this property is always set to `move`. """ x: int """The x-coordinate to move to.""" y: int """The y-coordinate to move to.""" class Screenshot(BaseModel): """A screenshot action.""" type: Literal["screenshot"] """Specifies the event type. For a screenshot action, this property is always set to `screenshot`. """ class Scroll(BaseModel): """A scroll action.""" scroll_x: int """The horizontal scroll distance.""" scroll_y: int """The vertical scroll distance.""" type: Literal["scroll"] """Specifies the event type. For a scroll action, this property is always set to `scroll`. """ x: int """The x-coordinate where the scroll occurred.""" y: int """The y-coordinate where the scroll occurred.""" class Type(BaseModel): """An action to type in text.""" text: str """The text to type.""" type: Literal["type"] """Specifies the event type. For a type action, this property is always set to `type`. """ class Wait(BaseModel): """A wait action.""" type: Literal["wait"] """Specifies the event type. For a wait action, this property is always set to `wait`. """ ComputerAction: TypeAlias = Annotated[ Union[Click, DoubleClick, Drag, Keypress, Move, Screenshot, Scroll, Type, Wait], PropertyInfo(discriminator="type") ] ================================================ FILE: src/openai/types/responses/computer_action_list.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List from typing_extensions import TypeAlias from .computer_action import ComputerAction __all__ = ["ComputerActionList"] ComputerActionList: TypeAlias = List[ComputerAction] ================================================ FILE: src/openai/types/responses/computer_action_list_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List, Union, Iterable from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import SequenceNotStr __all__ = [ "ComputerActionListParam", "ComputerActionParam", "Click", "DoubleClick", "Drag", "DragPath", "Keypress", "Move", "Screenshot", "Scroll", "Type", "Wait", ] class Click(TypedDict, total=False): """A click action.""" button: Required[Literal["left", "right", "wheel", "back", "forward"]] """Indicates which mouse button was pressed during the click. One of `left`, `right`, `wheel`, `back`, or `forward`. """ type: Required[Literal["click"]] """Specifies the event type. For a click action, this property is always `click`.""" x: Required[int] """The x-coordinate where the click occurred.""" y: Required[int] """The y-coordinate where the click occurred.""" class DoubleClick(TypedDict, total=False): """A double click action.""" type: Required[Literal["double_click"]] """Specifies the event type. For a double click action, this property is always set to `double_click`. """ x: Required[int] """The x-coordinate where the double click occurred.""" y: Required[int] """The y-coordinate where the double click occurred.""" class DragPath(TypedDict, total=False): """An x/y coordinate pair, e.g. `{ x: 100, y: 200 }`.""" x: Required[int] """The x-coordinate.""" y: Required[int] """The y-coordinate.""" class Drag(TypedDict, total=False): """A drag action.""" path: Required[Iterable[DragPath]] """An array of coordinates representing the path of the drag action. Coordinates will appear as an array of objects, eg ``` [ { x: 100, y: 200 }, { x: 200, y: 300 } ] ``` """ type: Required[Literal["drag"]] """Specifies the event type. For a drag action, this property is always set to `drag`. """ class Keypress(TypedDict, total=False): """A collection of keypresses the model would like to perform.""" keys: Required[SequenceNotStr[str]] """The combination of keys the model is requesting to be pressed. This is an array of strings, each representing a key. """ type: Required[Literal["keypress"]] """Specifies the event type. For a keypress action, this property is always set to `keypress`. """ class Move(TypedDict, total=False): """A mouse move action.""" type: Required[Literal["move"]] """Specifies the event type. For a move action, this property is always set to `move`. """ x: Required[int] """The x-coordinate to move to.""" y: Required[int] """The y-coordinate to move to.""" class Screenshot(TypedDict, total=False): """A screenshot action.""" type: Required[Literal["screenshot"]] """Specifies the event type. For a screenshot action, this property is always set to `screenshot`. """ class Scroll(TypedDict, total=False): """A scroll action.""" scroll_x: Required[int] """The horizontal scroll distance.""" scroll_y: Required[int] """The vertical scroll distance.""" type: Required[Literal["scroll"]] """Specifies the event type. For a scroll action, this property is always set to `scroll`. """ x: Required[int] """The x-coordinate where the scroll occurred.""" y: Required[int] """The y-coordinate where the scroll occurred.""" class Type(TypedDict, total=False): """An action to type in text.""" text: Required[str] """The text to type.""" type: Required[Literal["type"]] """Specifies the event type. For a type action, this property is always set to `type`. """ class Wait(TypedDict, total=False): """A wait action.""" type: Required[Literal["wait"]] """Specifies the event type. For a wait action, this property is always set to `wait`. """ ComputerActionParam: TypeAlias = Union[Click, DoubleClick, Drag, Keypress, Move, Screenshot, Scroll, Type, Wait] ComputerActionListParam: TypeAlias = List[ComputerActionParam] ================================================ FILE: src/openai/types/responses/computer_action_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import SequenceNotStr __all__ = [ "ComputerActionParam", "Click", "DoubleClick", "Drag", "DragPath", "Keypress", "Move", "Screenshot", "Scroll", "Type", "Wait", ] class Click(TypedDict, total=False): """A click action.""" button: Required[Literal["left", "right", "wheel", "back", "forward"]] """Indicates which mouse button was pressed during the click. One of `left`, `right`, `wheel`, `back`, or `forward`. """ type: Required[Literal["click"]] """Specifies the event type. For a click action, this property is always `click`.""" x: Required[int] """The x-coordinate where the click occurred.""" y: Required[int] """The y-coordinate where the click occurred.""" class DoubleClick(TypedDict, total=False): """A double click action.""" type: Required[Literal["double_click"]] """Specifies the event type. For a double click action, this property is always set to `double_click`. """ x: Required[int] """The x-coordinate where the double click occurred.""" y: Required[int] """The y-coordinate where the double click occurred.""" class DragPath(TypedDict, total=False): """An x/y coordinate pair, e.g. `{ x: 100, y: 200 }`.""" x: Required[int] """The x-coordinate.""" y: Required[int] """The y-coordinate.""" class Drag(TypedDict, total=False): """A drag action.""" path: Required[Iterable[DragPath]] """An array of coordinates representing the path of the drag action. Coordinates will appear as an array of objects, eg ``` [ { x: 100, y: 200 }, { x: 200, y: 300 } ] ``` """ type: Required[Literal["drag"]] """Specifies the event type. For a drag action, this property is always set to `drag`. """ class Keypress(TypedDict, total=False): """A collection of keypresses the model would like to perform.""" keys: Required[SequenceNotStr[str]] """The combination of keys the model is requesting to be pressed. This is an array of strings, each representing a key. """ type: Required[Literal["keypress"]] """Specifies the event type. For a keypress action, this property is always set to `keypress`. """ class Move(TypedDict, total=False): """A mouse move action.""" type: Required[Literal["move"]] """Specifies the event type. For a move action, this property is always set to `move`. """ x: Required[int] """The x-coordinate to move to.""" y: Required[int] """The y-coordinate to move to.""" class Screenshot(TypedDict, total=False): """A screenshot action.""" type: Required[Literal["screenshot"]] """Specifies the event type. For a screenshot action, this property is always set to `screenshot`. """ class Scroll(TypedDict, total=False): """A scroll action.""" scroll_x: Required[int] """The horizontal scroll distance.""" scroll_y: Required[int] """The vertical scroll distance.""" type: Required[Literal["scroll"]] """Specifies the event type. For a scroll action, this property is always set to `scroll`. """ x: Required[int] """The x-coordinate where the scroll occurred.""" y: Required[int] """The y-coordinate where the scroll occurred.""" class Type(TypedDict, total=False): """An action to type in text.""" text: Required[str] """The text to type.""" type: Required[Literal["type"]] """Specifies the event type. For a type action, this property is always set to `type`. """ class Wait(TypedDict, total=False): """A wait action.""" type: Required[Literal["wait"]] """Specifies the event type. For a wait action, this property is always set to `wait`. """ ComputerActionParam: TypeAlias = Union[Click, DoubleClick, Drag, Keypress, Move, Screenshot, Scroll, Type, Wait] ================================================ FILE: src/openai/types/responses/computer_tool.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ComputerTool"] class ComputerTool(BaseModel): """A tool that controls a virtual computer. Learn more about the [computer tool](https://platform.openai.com/docs/guides/tools-computer-use). """ type: Literal["computer"] """The type of the computer tool. Always `computer`.""" ================================================ FILE: src/openai/types/responses/computer_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ComputerToolParam"] class ComputerToolParam(TypedDict, total=False): """A tool that controls a virtual computer. Learn more about the [computer tool](https://platform.openai.com/docs/guides/tools-computer-use). """ type: Required[Literal["computer"]] """The type of the computer tool. Always `computer`.""" ================================================ FILE: src/openai/types/responses/computer_use_preview_tool.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ComputerUsePreviewTool"] class ComputerUsePreviewTool(BaseModel): """A tool that controls a virtual computer. Learn more about the [computer tool](https://platform.openai.com/docs/guides/tools-computer-use). """ display_height: int """The height of the computer display.""" display_width: int """The width of the computer display.""" environment: Literal["windows", "mac", "linux", "ubuntu", "browser"] """The type of computer environment to control.""" type: Literal["computer_use_preview"] """The type of the computer use tool. Always `computer_use_preview`.""" ================================================ FILE: src/openai/types/responses/computer_use_preview_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ComputerUsePreviewToolParam"] class ComputerUsePreviewToolParam(TypedDict, total=False): """A tool that controls a virtual computer. Learn more about the [computer tool](https://platform.openai.com/docs/guides/tools-computer-use). """ display_height: Required[int] """The height of the computer display.""" display_width: Required[int] """The width of the computer display.""" environment: Required[Literal["windows", "mac", "linux", "ubuntu", "browser"]] """The type of computer environment to control.""" type: Required[Literal["computer_use_preview"]] """The type of the computer use tool. Always `computer_use_preview`.""" ================================================ FILE: src/openai/types/responses/container_auto.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .inline_skill import InlineSkill from .skill_reference import SkillReference from .container_network_policy_disabled import ContainerNetworkPolicyDisabled from .container_network_policy_allowlist import ContainerNetworkPolicyAllowlist __all__ = ["ContainerAuto", "NetworkPolicy", "Skill"] NetworkPolicy: TypeAlias = Annotated[ Union[ContainerNetworkPolicyDisabled, ContainerNetworkPolicyAllowlist], PropertyInfo(discriminator="type") ] Skill: TypeAlias = Annotated[Union[SkillReference, InlineSkill], PropertyInfo(discriminator="type")] class ContainerAuto(BaseModel): type: Literal["container_auto"] """Automatically creates a container for this request""" file_ids: Optional[List[str]] = None """An optional list of uploaded files to make available to your code.""" memory_limit: Optional[Literal["1g", "4g", "16g", "64g"]] = None """The memory limit for the container.""" network_policy: Optional[NetworkPolicy] = None """Network access policy for the container.""" skills: Optional[List[Skill]] = None """An optional list of skills referenced by id or inline data.""" ================================================ FILE: src/openai/types/responses/container_auto_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import SequenceNotStr from .inline_skill_param import InlineSkillParam from .skill_reference_param import SkillReferenceParam from .container_network_policy_disabled_param import ContainerNetworkPolicyDisabledParam from .container_network_policy_allowlist_param import ContainerNetworkPolicyAllowlistParam __all__ = ["ContainerAutoParam", "NetworkPolicy", "Skill"] NetworkPolicy: TypeAlias = Union[ContainerNetworkPolicyDisabledParam, ContainerNetworkPolicyAllowlistParam] Skill: TypeAlias = Union[SkillReferenceParam, InlineSkillParam] class ContainerAutoParam(TypedDict, total=False): type: Required[Literal["container_auto"]] """Automatically creates a container for this request""" file_ids: SequenceNotStr[str] """An optional list of uploaded files to make available to your code.""" memory_limit: Optional[Literal["1g", "4g", "16g", "64g"]] """The memory limit for the container.""" network_policy: NetworkPolicy """Network access policy for the container.""" skills: Iterable[Skill] """An optional list of skills referenced by id or inline data.""" ================================================ FILE: src/openai/types/responses/container_network_policy_allowlist.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel from .container_network_policy_domain_secret import ContainerNetworkPolicyDomainSecret __all__ = ["ContainerNetworkPolicyAllowlist"] class ContainerNetworkPolicyAllowlist(BaseModel): allowed_domains: List[str] """A list of allowed domains when type is `allowlist`.""" type: Literal["allowlist"] """Allow outbound network access only to specified domains. Always `allowlist`.""" domain_secrets: Optional[List[ContainerNetworkPolicyDomainSecret]] = None """Optional domain-scoped secrets for allowlisted domains.""" ================================================ FILE: src/openai/types/responses/container_network_policy_allowlist_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Iterable from typing_extensions import Literal, Required, TypedDict from ..._types import SequenceNotStr from .container_network_policy_domain_secret_param import ContainerNetworkPolicyDomainSecretParam __all__ = ["ContainerNetworkPolicyAllowlistParam"] class ContainerNetworkPolicyAllowlistParam(TypedDict, total=False): allowed_domains: Required[SequenceNotStr[str]] """A list of allowed domains when type is `allowlist`.""" type: Required[Literal["allowlist"]] """Allow outbound network access only to specified domains. Always `allowlist`.""" domain_secrets: Iterable[ContainerNetworkPolicyDomainSecretParam] """Optional domain-scoped secrets for allowlisted domains.""" ================================================ FILE: src/openai/types/responses/container_network_policy_disabled.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ContainerNetworkPolicyDisabled"] class ContainerNetworkPolicyDisabled(BaseModel): type: Literal["disabled"] """Disable outbound network access. Always `disabled`.""" ================================================ FILE: src/openai/types/responses/container_network_policy_disabled_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ContainerNetworkPolicyDisabledParam"] class ContainerNetworkPolicyDisabledParam(TypedDict, total=False): type: Required[Literal["disabled"]] """Disable outbound network access. Always `disabled`.""" ================================================ FILE: src/openai/types/responses/container_network_policy_domain_secret.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from ..._models import BaseModel __all__ = ["ContainerNetworkPolicyDomainSecret"] class ContainerNetworkPolicyDomainSecret(BaseModel): domain: str """The domain associated with the secret.""" name: str """The name of the secret to inject for the domain.""" value: str """The secret value to inject for the domain.""" ================================================ FILE: src/openai/types/responses/container_network_policy_domain_secret_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Required, TypedDict __all__ = ["ContainerNetworkPolicyDomainSecretParam"] class ContainerNetworkPolicyDomainSecretParam(TypedDict, total=False): domain: Required[str] """The domain associated with the secret.""" name: Required[str] """The name of the secret to inject for the domain.""" value: Required[str] """The secret value to inject for the domain.""" ================================================ FILE: src/openai/types/responses/container_reference.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ContainerReference"] class ContainerReference(BaseModel): container_id: str """The ID of the referenced container.""" type: Literal["container_reference"] """References a container created with the /v1/containers endpoint""" ================================================ FILE: src/openai/types/responses/container_reference_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ContainerReferenceParam"] class ContainerReferenceParam(TypedDict, total=False): container_id: Required[str] """The ID of the referenced container.""" type: Required[Literal["container_reference"]] """References a container created with the /v1/containers endpoint""" ================================================ FILE: src/openai/types/responses/custom_tool.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel from ..shared.custom_tool_input_format import CustomToolInputFormat __all__ = ["CustomTool"] class CustomTool(BaseModel): """A custom tool that processes input using a specified format. Learn more about [custom tools](https://platform.openai.com/docs/guides/function-calling#custom-tools) """ name: str """The name of the custom tool, used to identify it in tool calls.""" type: Literal["custom"] """The type of the custom tool. Always `custom`.""" defer_loading: Optional[bool] = None """Whether this tool should be deferred and discovered via tool search.""" description: Optional[str] = None """Optional description of the custom tool, used to provide more context.""" format: Optional[CustomToolInputFormat] = None """The input format for the custom tool. Default is unconstrained text.""" ================================================ FILE: src/openai/types/responses/custom_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict from ..shared_params.custom_tool_input_format import CustomToolInputFormat __all__ = ["CustomToolParam"] class CustomToolParam(TypedDict, total=False): """A custom tool that processes input using a specified format. Learn more about [custom tools](https://platform.openai.com/docs/guides/function-calling#custom-tools) """ name: Required[str] """The name of the custom tool, used to identify it in tool calls.""" type: Required[Literal["custom"]] """The type of the custom tool. Always `custom`.""" defer_loading: bool """Whether this tool should be deferred and discovered via tool search.""" description: str """Optional description of the custom tool, used to provide more context.""" format: CustomToolInputFormat """The input format for the custom tool. Default is unconstrained text.""" ================================================ FILE: src/openai/types/responses/easy_input_message.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import Literal from ..._models import BaseModel from .response_input_message_content_list import ResponseInputMessageContentList __all__ = ["EasyInputMessage"] class EasyInputMessage(BaseModel): """ A message input to the model with a role indicating instruction following hierarchy. Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role. Messages with the `assistant` role are presumed to have been generated by the model in previous interactions. """ content: Union[str, ResponseInputMessageContentList] """ Text, image, or audio input to the model, used to generate a response. Can also contain previous assistant responses. """ role: Literal["user", "assistant", "system", "developer"] """The role of the message input. One of `user`, `assistant`, `system`, or `developer`. """ phase: Optional[Literal["commentary", "final_answer"]] = None """ Labels an `assistant` message as intermediate commentary (`commentary`) or the final answer (`final_answer`). For models like `gpt-5.3-codex` and beyond, when sending follow-up requests, preserve and resend phase on all assistant messages — dropping it can degrade performance. Not used for user messages. """ type: Optional[Literal["message"]] = None """The type of the message input. Always `message`.""" ================================================ FILE: src/openai/types/responses/easy_input_message_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Optional from typing_extensions import Literal, Required, TypedDict from .response_input_message_content_list_param import ResponseInputMessageContentListParam __all__ = ["EasyInputMessageParam"] class EasyInputMessageParam(TypedDict, total=False): """ A message input to the model with a role indicating instruction following hierarchy. Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role. Messages with the `assistant` role are presumed to have been generated by the model in previous interactions. """ content: Required[Union[str, ResponseInputMessageContentListParam]] """ Text, image, or audio input to the model, used to generate a response. Can also contain previous assistant responses. """ role: Required[Literal["user", "assistant", "system", "developer"]] """The role of the message input. One of `user`, `assistant`, `system`, or `developer`. """ phase: Optional[Literal["commentary", "final_answer"]] """ Labels an `assistant` message as intermediate commentary (`commentary`) or the final answer (`final_answer`). For models like `gpt-5.3-codex` and beyond, when sending follow-up requests, preserve and resend phase on all assistant messages — dropping it can degrade performance. Not used for user messages. """ type: Literal["message"] """The type of the message input. Always `message`.""" ================================================ FILE: src/openai/types/responses/file_search_tool.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, TypeAlias from ..._models import BaseModel from ..shared.compound_filter import CompoundFilter from ..shared.comparison_filter import ComparisonFilter __all__ = ["FileSearchTool", "Filters", "RankingOptions", "RankingOptionsHybridSearch"] Filters: TypeAlias = Union[ComparisonFilter, CompoundFilter, None] class RankingOptionsHybridSearch(BaseModel): """ Weights that control how reciprocal rank fusion balances semantic embedding matches versus sparse keyword matches when hybrid search is enabled. """ embedding_weight: float """The weight of the embedding in the reciprocal ranking fusion.""" text_weight: float """The weight of the text in the reciprocal ranking fusion.""" class RankingOptions(BaseModel): """Ranking options for search.""" hybrid_search: Optional[RankingOptionsHybridSearch] = None """ Weights that control how reciprocal rank fusion balances semantic embedding matches versus sparse keyword matches when hybrid search is enabled. """ ranker: Optional[Literal["auto", "default-2024-11-15"]] = None """The ranker to use for the file search.""" score_threshold: Optional[float] = None """The score threshold for the file search, a number between 0 and 1. Numbers closer to 1 will attempt to return only the most relevant results, but may return fewer results. """ class FileSearchTool(BaseModel): """A tool that searches for relevant content from uploaded files. Learn more about the [file search tool](https://platform.openai.com/docs/guides/tools-file-search). """ type: Literal["file_search"] """The type of the file search tool. Always `file_search`.""" vector_store_ids: List[str] """The IDs of the vector stores to search.""" filters: Optional[Filters] = None """A filter to apply.""" max_num_results: Optional[int] = None """The maximum number of results to return. This number should be between 1 and 50 inclusive. """ ranking_options: Optional[RankingOptions] = None """Ranking options for search.""" ================================================ FILE: src/openai/types/responses/file_search_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import SequenceNotStr from ..shared_params.compound_filter import CompoundFilter from ..shared_params.comparison_filter import ComparisonFilter __all__ = ["FileSearchToolParam", "Filters", "RankingOptions", "RankingOptionsHybridSearch"] Filters: TypeAlias = Union[ComparisonFilter, CompoundFilter] class RankingOptionsHybridSearch(TypedDict, total=False): """ Weights that control how reciprocal rank fusion balances semantic embedding matches versus sparse keyword matches when hybrid search is enabled. """ embedding_weight: Required[float] """The weight of the embedding in the reciprocal ranking fusion.""" text_weight: Required[float] """The weight of the text in the reciprocal ranking fusion.""" class RankingOptions(TypedDict, total=False): """Ranking options for search.""" hybrid_search: RankingOptionsHybridSearch """ Weights that control how reciprocal rank fusion balances semantic embedding matches versus sparse keyword matches when hybrid search is enabled. """ ranker: Literal["auto", "default-2024-11-15"] """The ranker to use for the file search.""" score_threshold: float """The score threshold for the file search, a number between 0 and 1. Numbers closer to 1 will attempt to return only the most relevant results, but may return fewer results. """ class FileSearchToolParam(TypedDict, total=False): """A tool that searches for relevant content from uploaded files. Learn more about the [file search tool](https://platform.openai.com/docs/guides/tools-file-search). """ type: Required[Literal["file_search"]] """The type of the file search tool. Always `file_search`.""" vector_store_ids: Required[SequenceNotStr[str]] """The IDs of the vector stores to search.""" filters: Optional[Filters] """A filter to apply.""" max_num_results: int """The maximum number of results to return. This number should be between 1 and 50 inclusive. """ ranking_options: RankingOptions """Ranking options for search.""" ================================================ FILE: src/openai/types/responses/function_shell_tool.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .container_auto import ContainerAuto from .local_environment import LocalEnvironment from .container_reference import ContainerReference __all__ = ["FunctionShellTool", "Environment"] Environment: TypeAlias = Annotated[ Union[ContainerAuto, LocalEnvironment, ContainerReference, None], PropertyInfo(discriminator="type") ] class FunctionShellTool(BaseModel): """A tool that allows the model to execute shell commands.""" type: Literal["shell"] """The type of the shell tool. Always `shell`.""" environment: Optional[Environment] = None ================================================ FILE: src/openai/types/responses/function_shell_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from .container_auto_param import ContainerAutoParam from .local_environment_param import LocalEnvironmentParam from .container_reference_param import ContainerReferenceParam __all__ = ["FunctionShellToolParam", "Environment"] Environment: TypeAlias = Union[ContainerAutoParam, LocalEnvironmentParam, ContainerReferenceParam] class FunctionShellToolParam(TypedDict, total=False): """A tool that allows the model to execute shell commands.""" type: Required[Literal["shell"]] """The type of the shell tool. Always `shell`.""" environment: Optional[Environment] ================================================ FILE: src/openai/types/responses/function_tool.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["FunctionTool"] class FunctionTool(BaseModel): """Defines a function in your own code the model can choose to call. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). """ name: str """The name of the function to call.""" parameters: Optional[Dict[str, object]] = None """A JSON schema object describing the parameters of the function.""" strict: Optional[bool] = None """Whether to enforce strict parameter validation. Default `true`.""" type: Literal["function"] """The type of the function tool. Always `function`.""" defer_loading: Optional[bool] = None """Whether this function is deferred and loaded via tool search.""" description: Optional[str] = None """A description of the function. Used by the model to determine whether or not to call the function. """ ================================================ FILE: src/openai/types/responses/function_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Optional from typing_extensions import Literal, Required, TypedDict __all__ = ["FunctionToolParam"] class FunctionToolParam(TypedDict, total=False): """Defines a function in your own code the model can choose to call. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). """ name: Required[str] """The name of the function to call.""" parameters: Required[Optional[Dict[str, object]]] """A JSON schema object describing the parameters of the function.""" strict: Required[Optional[bool]] """Whether to enforce strict parameter validation. Default `true`.""" type: Required[Literal["function"]] """The type of the function tool. Always `function`.""" defer_loading: bool """Whether this function is deferred and loaded via tool search.""" description: Optional[str] """A description of the function. Used by the model to determine whether or not to call the function. """ ================================================ FILE: src/openai/types/responses/inline_skill.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel from .inline_skill_source import InlineSkillSource __all__ = ["InlineSkill"] class InlineSkill(BaseModel): description: str """The description of the skill.""" name: str """The name of the skill.""" source: InlineSkillSource """Inline skill payload""" type: Literal["inline"] """Defines an inline skill for this request.""" ================================================ FILE: src/openai/types/responses/inline_skill_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict from .inline_skill_source_param import InlineSkillSourceParam __all__ = ["InlineSkillParam"] class InlineSkillParam(TypedDict, total=False): description: Required[str] """The description of the skill.""" name: Required[str] """The name of the skill.""" source: Required[InlineSkillSourceParam] """Inline skill payload""" type: Required[Literal["inline"]] """Defines an inline skill for this request.""" ================================================ FILE: src/openai/types/responses/inline_skill_source.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["InlineSkillSource"] class InlineSkillSource(BaseModel): """Inline skill payload""" data: str """Base64-encoded skill zip bundle.""" media_type: Literal["application/zip"] """The media type of the inline skill payload. Must be `application/zip`.""" type: Literal["base64"] """The type of the inline skill source. Must be `base64`.""" ================================================ FILE: src/openai/types/responses/inline_skill_source_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["InlineSkillSourceParam"] class InlineSkillSourceParam(TypedDict, total=False): """Inline skill payload""" data: Required[str] """Base64-encoded skill zip bundle.""" media_type: Required[Literal["application/zip"]] """The media type of the inline skill payload. Must be `application/zip`.""" type: Required[Literal["base64"]] """The type of the inline skill source. Must be `base64`.""" ================================================ FILE: src/openai/types/responses/input_item_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List from typing_extensions import Literal, TypedDict from .response_includable import ResponseIncludable __all__ = ["InputItemListParams"] class InputItemListParams(TypedDict, total=False): after: str """An item ID to list items after, used in pagination.""" include: List[ResponseIncludable] """Additional fields to include in the response. See the `include` parameter for Response creation above for more information. """ limit: int """A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. """ order: Literal["asc", "desc"] """The order to return the input items in. Default is `desc`. - `asc`: Return the input items in ascending order. - `desc`: Return the input items in descending order. """ ================================================ FILE: src/openai/types/responses/input_token_count_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable, Optional from typing_extensions import Literal, TypeAlias, TypedDict from .tool_param import ToolParam from .tool_choice_options import ToolChoiceOptions from .tool_choice_mcp_param import ToolChoiceMcpParam from .tool_choice_shell_param import ToolChoiceShellParam from .tool_choice_types_param import ToolChoiceTypesParam from ..shared_params.reasoning import Reasoning from .tool_choice_custom_param import ToolChoiceCustomParam from .response_input_item_param import ResponseInputItemParam from .tool_choice_allowed_param import ToolChoiceAllowedParam from .tool_choice_function_param import ToolChoiceFunctionParam from .tool_choice_apply_patch_param import ToolChoiceApplyPatchParam from .response_conversation_param_param import ResponseConversationParamParam from .response_format_text_config_param import ResponseFormatTextConfigParam __all__ = ["InputTokenCountParams", "Conversation", "Text", "ToolChoice"] class InputTokenCountParams(TypedDict, total=False): conversation: Optional[Conversation] """The conversation that this response belongs to. Items from this conversation are prepended to `input_items` for this response request. Input items and output items from this response are automatically added to this conversation after this response completes. """ input: Union[str, Iterable[ResponseInputItemParam], None] """Text, image, or file inputs to the model, used to generate a response""" instructions: Optional[str] """ A system (or developer) message inserted into the model's context. When used along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses. """ model: Optional[str] """Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. """ parallel_tool_calls: Optional[bool] """Whether to allow the model to run tool calls in parallel.""" previous_response_id: Optional[str] """The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://platform.openai.com/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`. """ reasoning: Optional[Reasoning] """ **gpt-5 and o-series models only** Configuration options for [reasoning models](https://platform.openai.com/docs/guides/reasoning). """ text: Optional[Text] """Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) """ tool_choice: Optional[ToolChoice] """Controls which tool the model should use, if any.""" tools: Optional[Iterable[ToolParam]] """An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. """ truncation: Literal["auto", "disabled"] """The truncation strategy to use for the model response. - `auto`: If the input to this Response exceeds the model's context window size, the model will truncate the response to fit the context window by dropping items from the beginning of the conversation. - `disabled` (default): If the input size will exceed the context window size for a model, the request will fail with a 400 error. """ Conversation: TypeAlias = Union[str, ResponseConversationParamParam] class Text(TypedDict, total=False): """Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) """ format: ResponseFormatTextConfigParam """An object specifying the format that the model must output. Configuring `{ "type": "json_schema" }` enables Structured Outputs, which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). The default format is `{ "type": "text" }` with no additional options. **Not recommended for gpt-4o and newer models:** Setting to `{ "type": "json_object" }` enables the older JSON mode, which ensures the message the model generates is valid JSON. Using `json_schema` is preferred for models that support it. """ verbosity: Optional[Literal["low", "medium", "high"]] """Constrains the verbosity of the model's response. Lower values will result in more concise responses, while higher values will result in more verbose responses. Currently supported values are `low`, `medium`, and `high`. """ ToolChoice: TypeAlias = Union[ ToolChoiceOptions, ToolChoiceAllowedParam, ToolChoiceTypesParam, ToolChoiceFunctionParam, ToolChoiceMcpParam, ToolChoiceCustomParam, ToolChoiceApplyPatchParam, ToolChoiceShellParam, ] ================================================ FILE: src/openai/types/responses/input_token_count_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["InputTokenCountResponse"] class InputTokenCountResponse(BaseModel): input_tokens: int object: Literal["response.input_tokens"] ================================================ FILE: src/openai/types/responses/local_environment.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel from .local_skill import LocalSkill __all__ = ["LocalEnvironment"] class LocalEnvironment(BaseModel): type: Literal["local"] """Use a local computer environment.""" skills: Optional[List[LocalSkill]] = None """An optional list of skills.""" ================================================ FILE: src/openai/types/responses/local_environment_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Iterable from typing_extensions import Literal, Required, TypedDict from .local_skill_param import LocalSkillParam __all__ = ["LocalEnvironmentParam"] class LocalEnvironmentParam(TypedDict, total=False): type: Required[Literal["local"]] """Use a local computer environment.""" skills: Iterable[LocalSkillParam] """An optional list of skills.""" ================================================ FILE: src/openai/types/responses/local_skill.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from ..._models import BaseModel __all__ = ["LocalSkill"] class LocalSkill(BaseModel): description: str """The description of the skill.""" name: str """The name of the skill.""" path: str """The path to the directory containing the skill.""" ================================================ FILE: src/openai/types/responses/local_skill_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Required, TypedDict __all__ = ["LocalSkillParam"] class LocalSkillParam(TypedDict, total=False): description: Required[str] """The description of the skill.""" name: Required[str] """The name of the skill.""" path: Required[str] """The path to the directory containing the skill.""" ================================================ FILE: src/openai/types/responses/namespace_tool.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .custom_tool import CustomTool __all__ = ["NamespaceTool", "Tool", "ToolFunction"] class ToolFunction(BaseModel): name: str type: Literal["function"] defer_loading: Optional[bool] = None """Whether this function should be deferred and discovered via tool search.""" description: Optional[str] = None parameters: Optional[object] = None strict: Optional[bool] = None Tool: TypeAlias = Annotated[Union[ToolFunction, CustomTool], PropertyInfo(discriminator="type")] class NamespaceTool(BaseModel): """Groups function/custom tools under a shared namespace.""" description: str """A description of the namespace shown to the model.""" name: str """The namespace name used in tool calls (for example, `crm`).""" tools: List[Tool] """The function/custom tools available inside this namespace.""" type: Literal["namespace"] """The type of the tool. Always `namespace`.""" ================================================ FILE: src/openai/types/responses/namespace_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from .custom_tool_param import CustomToolParam __all__ = ["NamespaceToolParam", "Tool", "ToolFunction"] class ToolFunction(TypedDict, total=False): name: Required[str] type: Required[Literal["function"]] defer_loading: bool """Whether this function should be deferred and discovered via tool search.""" description: Optional[str] parameters: Optional[object] strict: Optional[bool] Tool: TypeAlias = Union[ToolFunction, CustomToolParam] class NamespaceToolParam(TypedDict, total=False): """Groups function/custom tools under a shared namespace.""" description: Required[str] """A description of the namespace shown to the model.""" name: Required[str] """The namespace name used in tool calls (for example, `crm`).""" tools: Required[Iterable[Tool]] """The function/custom tools available inside this namespace.""" type: Required[Literal["namespace"]] """The type of the tool. Always `namespace`.""" ================================================ FILE: src/openai/types/responses/parsed_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import TYPE_CHECKING, List, Union, Generic, TypeVar, Optional from typing_extensions import Annotated, TypeAlias from ..._utils import PropertyInfo from .response import Response from ..._models import GenericModel from .response_output_item import ( McpCall, McpListTools, LocalShellCall, McpApprovalRequest, ImageGenerationCall, LocalShellCallAction, ) from .response_output_text import ResponseOutputText from .response_output_message import ResponseOutputMessage from .response_output_refusal import ResponseOutputRefusal from .response_reasoning_item import ResponseReasoningItem from .response_compaction_item import ResponseCompactionItem from .response_custom_tool_call import ResponseCustomToolCall from .response_tool_search_call import ResponseToolSearchCall from .response_computer_tool_call import ResponseComputerToolCall from .response_function_tool_call import ResponseFunctionToolCall from .response_function_web_search import ResponseFunctionWebSearch from .response_apply_patch_tool_call import ResponseApplyPatchToolCall from .response_file_search_tool_call import ResponseFileSearchToolCall from .response_tool_search_output_item import ResponseToolSearchOutputItem from .response_function_shell_tool_call import ResponseFunctionShellToolCall from .response_code_interpreter_tool_call import ResponseCodeInterpreterToolCall from .response_apply_patch_tool_call_output import ResponseApplyPatchToolCallOutput from .response_function_shell_tool_call_output import ResponseFunctionShellToolCallOutput __all__ = ["ParsedResponse", "ParsedResponseOutputMessage", "ParsedResponseOutputText"] ContentType = TypeVar("ContentType") # we need to disable this check because we're overriding properties # with subclasses of their types which is technically unsound as # properties can be mutated. # pyright: reportIncompatibleVariableOverride=false class ParsedResponseOutputText(ResponseOutputText, GenericModel, Generic[ContentType]): parsed: Optional[ContentType] = None ParsedContent: TypeAlias = Annotated[ Union[ParsedResponseOutputText[ContentType], ResponseOutputRefusal], PropertyInfo(discriminator="type"), ] class ParsedResponseOutputMessage(ResponseOutputMessage, GenericModel, Generic[ContentType]): if TYPE_CHECKING: content: List[ParsedContent[ContentType]] # type: ignore[assignment] else: content: List[ParsedContent] class ParsedResponseFunctionToolCall(ResponseFunctionToolCall): parsed_arguments: object = None __api_exclude__ = {"parsed_arguments"} ParsedResponseOutputItem: TypeAlias = Annotated[ Union[ ParsedResponseOutputMessage[ContentType], ParsedResponseFunctionToolCall, ResponseFileSearchToolCall, ResponseFunctionWebSearch, ResponseComputerToolCall, ResponseToolSearchCall, ResponseToolSearchOutputItem, ResponseReasoningItem, McpCall, McpApprovalRequest, ImageGenerationCall, LocalShellCall, LocalShellCallAction, McpListTools, ResponseCodeInterpreterToolCall, ResponseCustomToolCall, ResponseCompactionItem, ResponseFunctionShellToolCall, ResponseFunctionShellToolCallOutput, ResponseApplyPatchToolCall, ResponseApplyPatchToolCallOutput, ], PropertyInfo(discriminator="type"), ] class ParsedResponse(Response, GenericModel, Generic[ContentType]): if TYPE_CHECKING: output: List[ParsedResponseOutputItem[ContentType]] # type: ignore[assignment] else: output: List[ParsedResponseOutputItem] @property def output_parsed(self) -> Optional[ContentType]: for output in self.output: if output.type == "message": for content in output.content: if content.type == "output_text" and content.parsed: return content.parsed return None ================================================ FILE: src/openai/types/responses/response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, TypeAlias from .tool import Tool from ..._models import BaseModel from .response_error import ResponseError from .response_usage import ResponseUsage from .response_prompt import ResponsePrompt from .response_status import ResponseStatus from .tool_choice_mcp import ToolChoiceMcp from ..shared.metadata import Metadata from ..shared.reasoning import Reasoning from .tool_choice_shell import ToolChoiceShell from .tool_choice_types import ToolChoiceTypes from .tool_choice_custom import ToolChoiceCustom from .response_input_item import ResponseInputItem from .tool_choice_allowed import ToolChoiceAllowed from .tool_choice_options import ToolChoiceOptions from .response_output_item import ResponseOutputItem from .response_text_config import ResponseTextConfig from .tool_choice_function import ToolChoiceFunction from ..shared.responses_model import ResponsesModel from .tool_choice_apply_patch import ToolChoiceApplyPatch __all__ = ["Response", "IncompleteDetails", "ToolChoice", "Conversation"] class IncompleteDetails(BaseModel): """Details about why the response is incomplete.""" reason: Optional[Literal["max_output_tokens", "content_filter"]] = None """The reason why the response is incomplete.""" ToolChoice: TypeAlias = Union[ ToolChoiceOptions, ToolChoiceAllowed, ToolChoiceTypes, ToolChoiceFunction, ToolChoiceMcp, ToolChoiceCustom, ToolChoiceApplyPatch, ToolChoiceShell, ] class Conversation(BaseModel): """The conversation that this response belonged to. Input items and output items from this response were automatically added to this conversation. """ id: str """The unique ID of the conversation that this response was associated with.""" class Response(BaseModel): id: str """Unique identifier for this Response.""" created_at: float """Unix timestamp (in seconds) of when this Response was created.""" error: Optional[ResponseError] = None """An error object returned when the model fails to generate a Response.""" incomplete_details: Optional[IncompleteDetails] = None """Details about why the response is incomplete.""" instructions: Union[str, List[ResponseInputItem], None] = None """A system (or developer) message inserted into the model's context. When using along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses. """ metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ model: ResponsesModel """Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. """ object: Literal["response"] """The object type of this resource - always set to `response`.""" output: List[ResponseOutputItem] """An array of content items generated by the model. - The length and order of items in the `output` array is dependent on the model's response. - Rather than accessing the first item in the `output` array and assuming it's an `assistant` message with the content generated by the model, you might consider using the `output_text` property where supported in SDKs. """ parallel_tool_calls: bool """Whether to allow the model to run tool calls in parallel.""" temperature: Optional[float] = None """What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. """ tool_choice: ToolChoice """ How the model should select which tool (or tools) to use when generating a response. See the `tools` parameter to see how to specify which tools the model can call. """ tools: List[Tool] """An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. We support the following categories of tools: - **Built-in tools**: Tools that are provided by OpenAI that extend the model's capabilities, like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). - **MCP Tools**: Integrations with third-party systems via custom MCP servers or predefined connectors such as Google Drive and SharePoint. Learn more about [MCP Tools](https://platform.openai.com/docs/guides/tools-connectors-mcp). - **Function calls (custom tools)**: Functions that are defined by you, enabling the model to call your own code with strongly typed arguments and outputs. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). You can also use custom tools to call your own code. """ top_p: Optional[float] = None """ An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. """ background: Optional[bool] = None """ Whether to run the model response in the background. [Learn more](https://platform.openai.com/docs/guides/background). """ completed_at: Optional[float] = None """ Unix timestamp (in seconds) of when this Response was completed. Only present when the status is `completed`. """ conversation: Optional[Conversation] = None """The conversation that this response belonged to. Input items and output items from this response were automatically added to this conversation. """ max_output_tokens: Optional[int] = None """ An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). """ max_tool_calls: Optional[int] = None """ The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored. """ previous_response_id: Optional[str] = None """The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://platform.openai.com/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`. """ prompt: Optional[ResponsePrompt] = None """ Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). """ prompt_cache_key: Optional[str] = None """ Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://platform.openai.com/docs/guides/prompt-caching). """ prompt_cache_retention: Optional[Literal["in-memory", "24h"]] = None """The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). """ reasoning: Optional[Reasoning] = None """**gpt-5 and o-series models only** Configuration options for [reasoning models](https://platform.openai.com/docs/guides/reasoning). """ safety_identifier: Optional[str] = None """ A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). """ service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] = None """Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier. - When not set, the default behavior is 'auto'. When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. """ status: Optional[ResponseStatus] = None """The status of the response generation. One of `completed`, `failed`, `in_progress`, `cancelled`, `queued`, or `incomplete`. """ text: Optional[ResponseTextConfig] = None """Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) """ top_logprobs: Optional[int] = None """ An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. """ truncation: Optional[Literal["auto", "disabled"]] = None """The truncation strategy to use for the model response. - `auto`: If the input to this Response exceeds the model's context window size, the model will truncate the response to fit the context window by dropping items from the beginning of the conversation. - `disabled` (default): If the input size will exceed the context window size for a model, the request will fail with a 400 error. """ usage: Optional[ResponseUsage] = None """ Represents token usage details including input tokens, output tokens, a breakdown of output tokens, and the total tokens used. """ user: Optional[str] = None """This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations. A stable identifier for your end-users. Used to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). """ @property def output_text(self) -> str: """Convenience property that aggregates all `output_text` items from the `output` list. If no `output_text` content blocks exist, then an empty string is returned. """ texts: List[str] = [] for output in self.output: if output.type == "message": for content in output.content: if content.type == "output_text": texts.append(content.text) return "".join(texts) ================================================ FILE: src/openai/types/responses/response_apply_patch_tool_call.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = [ "ResponseApplyPatchToolCall", "Operation", "OperationCreateFile", "OperationDeleteFile", "OperationUpdateFile", ] class OperationCreateFile(BaseModel): """Instruction describing how to create a file via the apply_patch tool.""" diff: str """Diff to apply.""" path: str """Path of the file to create.""" type: Literal["create_file"] """Create a new file with the provided diff.""" class OperationDeleteFile(BaseModel): """Instruction describing how to delete a file via the apply_patch tool.""" path: str """Path of the file to delete.""" type: Literal["delete_file"] """Delete the specified file.""" class OperationUpdateFile(BaseModel): """Instruction describing how to update a file via the apply_patch tool.""" diff: str """Diff to apply.""" path: str """Path of the file to update.""" type: Literal["update_file"] """Update an existing file with the provided diff.""" Operation: TypeAlias = Annotated[ Union[OperationCreateFile, OperationDeleteFile, OperationUpdateFile], PropertyInfo(discriminator="type") ] class ResponseApplyPatchToolCall(BaseModel): """A tool call that applies file diffs by creating, deleting, or updating files.""" id: str """The unique ID of the apply patch tool call. Populated when this item is returned via API. """ call_id: str """The unique ID of the apply patch tool call generated by the model.""" operation: Operation """ One of the create_file, delete_file, or update_file operations applied via apply_patch. """ status: Literal["in_progress", "completed"] """The status of the apply patch tool call. One of `in_progress` or `completed`.""" type: Literal["apply_patch_call"] """The type of the item. Always `apply_patch_call`.""" created_by: Optional[str] = None """The ID of the entity that created this tool call.""" ================================================ FILE: src/openai/types/responses/response_apply_patch_tool_call_output.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseApplyPatchToolCallOutput"] class ResponseApplyPatchToolCallOutput(BaseModel): """The output emitted by an apply patch tool call.""" id: str """The unique ID of the apply patch tool call output. Populated when this item is returned via API. """ call_id: str """The unique ID of the apply patch tool call generated by the model.""" status: Literal["completed", "failed"] """The status of the apply patch tool call output. One of `completed` or `failed`.""" type: Literal["apply_patch_call_output"] """The type of the item. Always `apply_patch_call_output`.""" created_by: Optional[str] = None """The ID of the entity that created this tool call output.""" output: Optional[str] = None """Optional textual output returned by the apply patch tool.""" ================================================ FILE: src/openai/types/responses/response_audio_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseAudioDeltaEvent"] class ResponseAudioDeltaEvent(BaseModel): """Emitted when there is a partial audio response.""" delta: str """A chunk of Base64 encoded response audio bytes.""" sequence_number: int """A sequence number for this chunk of the stream response.""" type: Literal["response.audio.delta"] """The type of the event. Always `response.audio.delta`.""" ================================================ FILE: src/openai/types/responses/response_audio_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseAudioDoneEvent"] class ResponseAudioDoneEvent(BaseModel): """Emitted when the audio response is complete.""" sequence_number: int """The sequence number of the delta.""" type: Literal["response.audio.done"] """The type of the event. Always `response.audio.done`.""" ================================================ FILE: src/openai/types/responses/response_audio_transcript_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseAudioTranscriptDeltaEvent"] class ResponseAudioTranscriptDeltaEvent(BaseModel): """Emitted when there is a partial transcript of audio.""" delta: str """The partial transcript of the audio response.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.audio.transcript.delta"] """The type of the event. Always `response.audio.transcript.delta`.""" ================================================ FILE: src/openai/types/responses/response_audio_transcript_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseAudioTranscriptDoneEvent"] class ResponseAudioTranscriptDoneEvent(BaseModel): """Emitted when the full audio transcript is completed.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.audio.transcript.done"] """The type of the event. Always `response.audio.transcript.done`.""" ================================================ FILE: src/openai/types/responses/response_code_interpreter_call_code_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseCodeInterpreterCallCodeDeltaEvent"] class ResponseCodeInterpreterCallCodeDeltaEvent(BaseModel): """Emitted when a partial code snippet is streamed by the code interpreter.""" delta: str """The partial code snippet being streamed by the code interpreter.""" item_id: str """The unique identifier of the code interpreter tool call item.""" output_index: int """ The index of the output item in the response for which the code is being streamed. """ sequence_number: int """The sequence number of this event, used to order streaming events.""" type: Literal["response.code_interpreter_call_code.delta"] """The type of the event. Always `response.code_interpreter_call_code.delta`.""" ================================================ FILE: src/openai/types/responses/response_code_interpreter_call_code_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseCodeInterpreterCallCodeDoneEvent"] class ResponseCodeInterpreterCallCodeDoneEvent(BaseModel): """Emitted when the code snippet is finalized by the code interpreter.""" code: str """The final code snippet output by the code interpreter.""" item_id: str """The unique identifier of the code interpreter tool call item.""" output_index: int """The index of the output item in the response for which the code is finalized.""" sequence_number: int """The sequence number of this event, used to order streaming events.""" type: Literal["response.code_interpreter_call_code.done"] """The type of the event. Always `response.code_interpreter_call_code.done`.""" ================================================ FILE: src/openai/types/responses/response_code_interpreter_call_completed_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseCodeInterpreterCallCompletedEvent"] class ResponseCodeInterpreterCallCompletedEvent(BaseModel): """Emitted when the code interpreter call is completed.""" item_id: str """The unique identifier of the code interpreter tool call item.""" output_index: int """ The index of the output item in the response for which the code interpreter call is completed. """ sequence_number: int """The sequence number of this event, used to order streaming events.""" type: Literal["response.code_interpreter_call.completed"] """The type of the event. Always `response.code_interpreter_call.completed`.""" ================================================ FILE: src/openai/types/responses/response_code_interpreter_call_in_progress_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseCodeInterpreterCallInProgressEvent"] class ResponseCodeInterpreterCallInProgressEvent(BaseModel): """Emitted when a code interpreter call is in progress.""" item_id: str """The unique identifier of the code interpreter tool call item.""" output_index: int """ The index of the output item in the response for which the code interpreter call is in progress. """ sequence_number: int """The sequence number of this event, used to order streaming events.""" type: Literal["response.code_interpreter_call.in_progress"] """The type of the event. Always `response.code_interpreter_call.in_progress`.""" ================================================ FILE: src/openai/types/responses/response_code_interpreter_call_interpreting_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseCodeInterpreterCallInterpretingEvent"] class ResponseCodeInterpreterCallInterpretingEvent(BaseModel): """Emitted when the code interpreter is actively interpreting the code snippet.""" item_id: str """The unique identifier of the code interpreter tool call item.""" output_index: int """ The index of the output item in the response for which the code interpreter is interpreting code. """ sequence_number: int """The sequence number of this event, used to order streaming events.""" type: Literal["response.code_interpreter_call.interpreting"] """The type of the event. Always `response.code_interpreter_call.interpreting`.""" ================================================ FILE: src/openai/types/responses/response_code_interpreter_tool_call.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = ["ResponseCodeInterpreterToolCall", "Output", "OutputLogs", "OutputImage"] class OutputLogs(BaseModel): """The logs output from the code interpreter.""" logs: str """The logs output from the code interpreter.""" type: Literal["logs"] """The type of the output. Always `logs`.""" class OutputImage(BaseModel): """The image output from the code interpreter.""" type: Literal["image"] """The type of the output. Always `image`.""" url: str """The URL of the image output from the code interpreter.""" Output: TypeAlias = Annotated[Union[OutputLogs, OutputImage], PropertyInfo(discriminator="type")] class ResponseCodeInterpreterToolCall(BaseModel): """A tool call to run code.""" id: str """The unique ID of the code interpreter tool call.""" code: Optional[str] = None """The code to run, or null if not available.""" container_id: str """The ID of the container used to run the code.""" outputs: Optional[List[Output]] = None """ The outputs generated by the code interpreter, such as logs or images. Can be null if no outputs are available. """ status: Literal["in_progress", "completed", "incomplete", "interpreting", "failed"] """The status of the code interpreter tool call. Valid values are `in_progress`, `completed`, `incomplete`, `interpreting`, and `failed`. """ type: Literal["code_interpreter_call"] """The type of the code interpreter tool call. Always `code_interpreter_call`.""" ================================================ FILE: src/openai/types/responses/response_code_interpreter_tool_call_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict __all__ = ["ResponseCodeInterpreterToolCallParam", "Output", "OutputLogs", "OutputImage"] class OutputLogs(TypedDict, total=False): """The logs output from the code interpreter.""" logs: Required[str] """The logs output from the code interpreter.""" type: Required[Literal["logs"]] """The type of the output. Always `logs`.""" class OutputImage(TypedDict, total=False): """The image output from the code interpreter.""" type: Required[Literal["image"]] """The type of the output. Always `image`.""" url: Required[str] """The URL of the image output from the code interpreter.""" Output: TypeAlias = Union[OutputLogs, OutputImage] class ResponseCodeInterpreterToolCallParam(TypedDict, total=False): """A tool call to run code.""" id: Required[str] """The unique ID of the code interpreter tool call.""" code: Required[Optional[str]] """The code to run, or null if not available.""" container_id: Required[str] """The ID of the container used to run the code.""" outputs: Required[Optional[Iterable[Output]]] """ The outputs generated by the code interpreter, such as logs or images. Can be null if no outputs are available. """ status: Required[Literal["in_progress", "completed", "incomplete", "interpreting", "failed"]] """The status of the code interpreter tool call. Valid values are `in_progress`, `completed`, `incomplete`, `interpreting`, and `failed`. """ type: Required[Literal["code_interpreter_call"]] """The type of the code interpreter tool call. Always `code_interpreter_call`.""" ================================================ FILE: src/openai/types/responses/response_compact_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable, Optional from typing_extensions import Literal, Required, TypedDict from .response_input_item_param import ResponseInputItemParam __all__ = ["ResponseCompactParams"] class ResponseCompactParams(TypedDict, total=False): model: Required[ Union[ Literal[ "gpt-5.4", "gpt-5.4-mini", "gpt-5.4-nano", "gpt-5.4-mini-2026-03-17", "gpt-5.4-nano-2026-03-17", "gpt-5.3-chat-latest", "gpt-5.2", "gpt-5.2-2025-12-11", "gpt-5.2-chat-latest", "gpt-5.2-pro", "gpt-5.2-pro-2025-12-11", "gpt-5.1", "gpt-5.1-2025-11-13", "gpt-5.1-codex", "gpt-5.1-mini", "gpt-5.1-chat-latest", "gpt-5", "gpt-5-mini", "gpt-5-nano", "gpt-5-2025-08-07", "gpt-5-mini-2025-08-07", "gpt-5-nano-2025-08-07", "gpt-5-chat-latest", "gpt-4.1", "gpt-4.1-mini", "gpt-4.1-nano", "gpt-4.1-2025-04-14", "gpt-4.1-mini-2025-04-14", "gpt-4.1-nano-2025-04-14", "o4-mini", "o4-mini-2025-04-16", "o3", "o3-2025-04-16", "o3-mini", "o3-mini-2025-01-31", "o1", "o1-2024-12-17", "o1-preview", "o1-preview-2024-09-12", "o1-mini", "o1-mini-2024-09-12", "gpt-4o", "gpt-4o-2024-11-20", "gpt-4o-2024-08-06", "gpt-4o-2024-05-13", "gpt-4o-audio-preview", "gpt-4o-audio-preview-2024-10-01", "gpt-4o-audio-preview-2024-12-17", "gpt-4o-audio-preview-2025-06-03", "gpt-4o-mini-audio-preview", "gpt-4o-mini-audio-preview-2024-12-17", "gpt-4o-search-preview", "gpt-4o-mini-search-preview", "gpt-4o-search-preview-2025-03-11", "gpt-4o-mini-search-preview-2025-03-11", "chatgpt-4o-latest", "codex-mini-latest", "gpt-4o-mini", "gpt-4o-mini-2024-07-18", "gpt-4-turbo", "gpt-4-turbo-2024-04-09", "gpt-4-0125-preview", "gpt-4-turbo-preview", "gpt-4-1106-preview", "gpt-4-vision-preview", "gpt-4", "gpt-4-0314", "gpt-4-0613", "gpt-4-32k", "gpt-4-32k-0314", "gpt-4-32k-0613", "gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-3.5-turbo-0301", "gpt-3.5-turbo-0613", "gpt-3.5-turbo-1106", "gpt-3.5-turbo-0125", "gpt-3.5-turbo-16k-0613", "o1-pro", "o1-pro-2025-03-19", "o3-pro", "o3-pro-2025-06-10", "o3-deep-research", "o3-deep-research-2025-06-26", "o4-mini-deep-research", "o4-mini-deep-research-2025-06-26", "computer-use-preview", "computer-use-preview-2025-03-11", "gpt-5-codex", "gpt-5-pro", "gpt-5-pro-2025-10-06", "gpt-5.1-codex-max", ], str, None, ] ] """Model ID used to generate the response, like `gpt-5` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. """ input: Union[str, Iterable[ResponseInputItemParam], None] """Text, image, or file inputs to the model, used to generate a response""" instructions: Optional[str] """ A system (or developer) message inserted into the model's context. When used along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses. """ previous_response_id: Optional[str] """The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://platform.openai.com/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`. """ prompt_cache_key: Optional[str] """A key to use when reading from or writing to the prompt cache.""" ================================================ FILE: src/openai/types/responses/response_compaction_item.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseCompactionItem"] class ResponseCompactionItem(BaseModel): """ A compaction item generated by the [`v1/responses/compact` API](https://platform.openai.com/docs/api-reference/responses/compact). """ id: str """The unique ID of the compaction item.""" encrypted_content: str """The encrypted content that was produced by compaction.""" type: Literal["compaction"] """The type of the item. Always `compaction`.""" created_by: Optional[str] = None """The identifier of the actor that created the item.""" ================================================ FILE: src/openai/types/responses/response_compaction_item_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseCompactionItemParam"] class ResponseCompactionItemParam(BaseModel): """ A compaction item generated by the [`v1/responses/compact` API](https://platform.openai.com/docs/api-reference/responses/compact). """ encrypted_content: str """The encrypted content of the compaction summary.""" type: Literal["compaction"] """The type of the item. Always `compaction`.""" id: Optional[str] = None """The ID of the compaction item.""" ================================================ FILE: src/openai/types/responses/response_compaction_item_param_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Literal, Required, TypedDict __all__ = ["ResponseCompactionItemParamParam"] class ResponseCompactionItemParamParam(TypedDict, total=False): """ A compaction item generated by the [`v1/responses/compact` API](https://platform.openai.com/docs/api-reference/responses/compact). """ encrypted_content: Required[str] """The encrypted content of the compaction summary.""" type: Required[Literal["compaction"]] """The type of the item. Always `compaction`.""" id: Optional[str] """The ID of the compaction item.""" ================================================ FILE: src/openai/types/responses/response_completed_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .response import Response from ..._models import BaseModel __all__ = ["ResponseCompletedEvent"] class ResponseCompletedEvent(BaseModel): """Emitted when the model response is complete.""" response: Response """Properties of the completed response.""" sequence_number: int """The sequence number for this event.""" type: Literal["response.completed"] """The type of the event. Always `response.completed`.""" ================================================ FILE: src/openai/types/responses/response_computer_tool_call.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .computer_action_list import ComputerActionList __all__ = [ "ResponseComputerToolCall", "PendingSafetyCheck", "Action", "ActionClick", "ActionDoubleClick", "ActionDrag", "ActionDragPath", "ActionKeypress", "ActionMove", "ActionScreenshot", "ActionScroll", "ActionType", "ActionWait", ] class PendingSafetyCheck(BaseModel): """A pending safety check for the computer call.""" id: str """The ID of the pending safety check.""" code: Optional[str] = None """The type of the pending safety check.""" message: Optional[str] = None """Details about the pending safety check.""" class ActionClick(BaseModel): """A click action.""" button: Literal["left", "right", "wheel", "back", "forward"] """Indicates which mouse button was pressed during the click. One of `left`, `right`, `wheel`, `back`, or `forward`. """ type: Literal["click"] """Specifies the event type. For a click action, this property is always `click`.""" x: int """The x-coordinate where the click occurred.""" y: int """The y-coordinate where the click occurred.""" class ActionDoubleClick(BaseModel): """A double click action.""" type: Literal["double_click"] """Specifies the event type. For a double click action, this property is always set to `double_click`. """ x: int """The x-coordinate where the double click occurred.""" y: int """The y-coordinate where the double click occurred.""" class ActionDragPath(BaseModel): """An x/y coordinate pair, e.g. `{ x: 100, y: 200 }`.""" x: int """The x-coordinate.""" y: int """The y-coordinate.""" class ActionDrag(BaseModel): """A drag action.""" path: List[ActionDragPath] """An array of coordinates representing the path of the drag action. Coordinates will appear as an array of objects, eg ``` [ { x: 100, y: 200 }, { x: 200, y: 300 } ] ``` """ type: Literal["drag"] """Specifies the event type. For a drag action, this property is always set to `drag`. """ class ActionKeypress(BaseModel): """A collection of keypresses the model would like to perform.""" keys: List[str] """The combination of keys the model is requesting to be pressed. This is an array of strings, each representing a key. """ type: Literal["keypress"] """Specifies the event type. For a keypress action, this property is always set to `keypress`. """ class ActionMove(BaseModel): """A mouse move action.""" type: Literal["move"] """Specifies the event type. For a move action, this property is always set to `move`. """ x: int """The x-coordinate to move to.""" y: int """The y-coordinate to move to.""" class ActionScreenshot(BaseModel): """A screenshot action.""" type: Literal["screenshot"] """Specifies the event type. For a screenshot action, this property is always set to `screenshot`. """ class ActionScroll(BaseModel): """A scroll action.""" scroll_x: int """The horizontal scroll distance.""" scroll_y: int """The vertical scroll distance.""" type: Literal["scroll"] """Specifies the event type. For a scroll action, this property is always set to `scroll`. """ x: int """The x-coordinate where the scroll occurred.""" y: int """The y-coordinate where the scroll occurred.""" class ActionType(BaseModel): """An action to type in text.""" text: str """The text to type.""" type: Literal["type"] """Specifies the event type. For a type action, this property is always set to `type`. """ class ActionWait(BaseModel): """A wait action.""" type: Literal["wait"] """Specifies the event type. For a wait action, this property is always set to `wait`. """ Action: TypeAlias = Annotated[ Union[ ActionClick, ActionDoubleClick, ActionDrag, ActionKeypress, ActionMove, ActionScreenshot, ActionScroll, ActionType, ActionWait, ], PropertyInfo(discriminator="type"), ] class ResponseComputerToolCall(BaseModel): """A tool call to a computer use tool. See the [computer use guide](https://platform.openai.com/docs/guides/tools-computer-use) for more information. """ id: str """The unique ID of the computer call.""" call_id: str """An identifier used when responding to the tool call with output.""" pending_safety_checks: List[PendingSafetyCheck] """The pending safety checks for the computer call.""" status: Literal["in_progress", "completed", "incomplete"] """The status of the item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API. """ type: Literal["computer_call"] """The type of the computer call. Always `computer_call`.""" action: Optional[Action] = None """A click action.""" actions: Optional[ComputerActionList] = None """Flattened batched actions for `computer_use`. Each action includes an `type` discriminator and action-specific fields. """ ================================================ FILE: src/openai/types/responses/response_computer_tool_call_output_item.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel from .response_computer_tool_call_output_screenshot import ResponseComputerToolCallOutputScreenshot __all__ = ["ResponseComputerToolCallOutputItem", "AcknowledgedSafetyCheck"] class AcknowledgedSafetyCheck(BaseModel): """A pending safety check for the computer call.""" id: str """The ID of the pending safety check.""" code: Optional[str] = None """The type of the pending safety check.""" message: Optional[str] = None """Details about the pending safety check.""" class ResponseComputerToolCallOutputItem(BaseModel): id: str """The unique ID of the computer call tool output.""" call_id: str """The ID of the computer tool call that produced the output.""" output: ResponseComputerToolCallOutputScreenshot """A computer screenshot image used with the computer use tool.""" type: Literal["computer_call_output"] """The type of the computer tool call output. Always `computer_call_output`.""" acknowledged_safety_checks: Optional[List[AcknowledgedSafetyCheck]] = None """ The safety checks reported by the API that have been acknowledged by the developer. """ status: Optional[Literal["in_progress", "completed", "incomplete"]] = None """The status of the message input. One of `in_progress`, `completed`, or `incomplete`. Populated when input items are returned via API. """ ================================================ FILE: src/openai/types/responses/response_computer_tool_call_output_screenshot.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseComputerToolCallOutputScreenshot"] class ResponseComputerToolCallOutputScreenshot(BaseModel): """A computer screenshot image used with the computer use tool.""" type: Literal["computer_screenshot"] """Specifies the event type. For a computer screenshot, this property is always set to `computer_screenshot`. """ file_id: Optional[str] = None """The identifier of an uploaded file that contains the screenshot.""" image_url: Optional[str] = None """The URL of the screenshot image.""" ================================================ FILE: src/openai/types/responses/response_computer_tool_call_output_screenshot_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ResponseComputerToolCallOutputScreenshotParam"] class ResponseComputerToolCallOutputScreenshotParam(TypedDict, total=False): """A computer screenshot image used with the computer use tool.""" type: Required[Literal["computer_screenshot"]] """Specifies the event type. For a computer screenshot, this property is always set to `computer_screenshot`. """ file_id: str """The identifier of an uploaded file that contains the screenshot.""" image_url: str """The URL of the screenshot image.""" ================================================ FILE: src/openai/types/responses/response_computer_tool_call_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import SequenceNotStr from .computer_action_list_param import ComputerActionListParam __all__ = [ "ResponseComputerToolCallParam", "PendingSafetyCheck", "Action", "ActionClick", "ActionDoubleClick", "ActionDrag", "ActionDragPath", "ActionKeypress", "ActionMove", "ActionScreenshot", "ActionScroll", "ActionType", "ActionWait", ] class PendingSafetyCheck(TypedDict, total=False): """A pending safety check for the computer call.""" id: Required[str] """The ID of the pending safety check.""" code: Optional[str] """The type of the pending safety check.""" message: Optional[str] """Details about the pending safety check.""" class ActionClick(TypedDict, total=False): """A click action.""" button: Required[Literal["left", "right", "wheel", "back", "forward"]] """Indicates which mouse button was pressed during the click. One of `left`, `right`, `wheel`, `back`, or `forward`. """ type: Required[Literal["click"]] """Specifies the event type. For a click action, this property is always `click`.""" x: Required[int] """The x-coordinate where the click occurred.""" y: Required[int] """The y-coordinate where the click occurred.""" class ActionDoubleClick(TypedDict, total=False): """A double click action.""" type: Required[Literal["double_click"]] """Specifies the event type. For a double click action, this property is always set to `double_click`. """ x: Required[int] """The x-coordinate where the double click occurred.""" y: Required[int] """The y-coordinate where the double click occurred.""" class ActionDragPath(TypedDict, total=False): """An x/y coordinate pair, e.g. `{ x: 100, y: 200 }`.""" x: Required[int] """The x-coordinate.""" y: Required[int] """The y-coordinate.""" class ActionDrag(TypedDict, total=False): """A drag action.""" path: Required[Iterable[ActionDragPath]] """An array of coordinates representing the path of the drag action. Coordinates will appear as an array of objects, eg ``` [ { x: 100, y: 200 }, { x: 200, y: 300 } ] ``` """ type: Required[Literal["drag"]] """Specifies the event type. For a drag action, this property is always set to `drag`. """ class ActionKeypress(TypedDict, total=False): """A collection of keypresses the model would like to perform.""" keys: Required[SequenceNotStr[str]] """The combination of keys the model is requesting to be pressed. This is an array of strings, each representing a key. """ type: Required[Literal["keypress"]] """Specifies the event type. For a keypress action, this property is always set to `keypress`. """ class ActionMove(TypedDict, total=False): """A mouse move action.""" type: Required[Literal["move"]] """Specifies the event type. For a move action, this property is always set to `move`. """ x: Required[int] """The x-coordinate to move to.""" y: Required[int] """The y-coordinate to move to.""" class ActionScreenshot(TypedDict, total=False): """A screenshot action.""" type: Required[Literal["screenshot"]] """Specifies the event type. For a screenshot action, this property is always set to `screenshot`. """ class ActionScroll(TypedDict, total=False): """A scroll action.""" scroll_x: Required[int] """The horizontal scroll distance.""" scroll_y: Required[int] """The vertical scroll distance.""" type: Required[Literal["scroll"]] """Specifies the event type. For a scroll action, this property is always set to `scroll`. """ x: Required[int] """The x-coordinate where the scroll occurred.""" y: Required[int] """The y-coordinate where the scroll occurred.""" class ActionType(TypedDict, total=False): """An action to type in text.""" text: Required[str] """The text to type.""" type: Required[Literal["type"]] """Specifies the event type. For a type action, this property is always set to `type`. """ class ActionWait(TypedDict, total=False): """A wait action.""" type: Required[Literal["wait"]] """Specifies the event type. For a wait action, this property is always set to `wait`. """ Action: TypeAlias = Union[ ActionClick, ActionDoubleClick, ActionDrag, ActionKeypress, ActionMove, ActionScreenshot, ActionScroll, ActionType, ActionWait, ] class ResponseComputerToolCallParam(TypedDict, total=False): """A tool call to a computer use tool. See the [computer use guide](https://platform.openai.com/docs/guides/tools-computer-use) for more information. """ id: Required[str] """The unique ID of the computer call.""" call_id: Required[str] """An identifier used when responding to the tool call with output.""" pending_safety_checks: Required[Iterable[PendingSafetyCheck]] """The pending safety checks for the computer call.""" status: Required[Literal["in_progress", "completed", "incomplete"]] """The status of the item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API. """ type: Required[Literal["computer_call"]] """The type of the computer call. Always `computer_call`.""" action: Action """A click action.""" actions: ComputerActionListParam """Flattened batched actions for `computer_use`. Each action includes an `type` discriminator and action-specific fields. """ ================================================ FILE: src/openai/types/responses/response_container_reference.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseContainerReference"] class ResponseContainerReference(BaseModel): """Represents a container created with /v1/containers.""" container_id: str type: Literal["container_reference"] """The environment type. Always `container_reference`.""" ================================================ FILE: src/openai/types/responses/response_content_part_added_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .response_output_text import ResponseOutputText from .response_output_refusal import ResponseOutputRefusal __all__ = ["ResponseContentPartAddedEvent", "Part", "PartReasoningText"] class PartReasoningText(BaseModel): """Reasoning text from the model.""" text: str """The reasoning text from the model.""" type: Literal["reasoning_text"] """The type of the reasoning text. Always `reasoning_text`.""" Part: TypeAlias = Annotated[ Union[ResponseOutputText, ResponseOutputRefusal, PartReasoningText], PropertyInfo(discriminator="type") ] class ResponseContentPartAddedEvent(BaseModel): """Emitted when a new content part is added.""" content_index: int """The index of the content part that was added.""" item_id: str """The ID of the output item that the content part was added to.""" output_index: int """The index of the output item that the content part was added to.""" part: Part """The content part that was added.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.content_part.added"] """The type of the event. Always `response.content_part.added`.""" ================================================ FILE: src/openai/types/responses/response_content_part_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .response_output_text import ResponseOutputText from .response_output_refusal import ResponseOutputRefusal __all__ = ["ResponseContentPartDoneEvent", "Part", "PartReasoningText"] class PartReasoningText(BaseModel): """Reasoning text from the model.""" text: str """The reasoning text from the model.""" type: Literal["reasoning_text"] """The type of the reasoning text. Always `reasoning_text`.""" Part: TypeAlias = Annotated[ Union[ResponseOutputText, ResponseOutputRefusal, PartReasoningText], PropertyInfo(discriminator="type") ] class ResponseContentPartDoneEvent(BaseModel): """Emitted when a content part is done.""" content_index: int """The index of the content part that is done.""" item_id: str """The ID of the output item that the content part was added to.""" output_index: int """The index of the output item that the content part was added to.""" part: Part """The content part that is done.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.content_part.done"] """The type of the event. Always `response.content_part.done`.""" ================================================ FILE: src/openai/types/responses/response_conversation_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from ..._models import BaseModel __all__ = ["ResponseConversationParam"] class ResponseConversationParam(BaseModel): """The conversation that this response belongs to.""" id: str """The unique ID of the conversation.""" ================================================ FILE: src/openai/types/responses/response_conversation_param_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Required, TypedDict __all__ = ["ResponseConversationParamParam"] class ResponseConversationParamParam(TypedDict, total=False): """The conversation that this response belongs to.""" id: Required[str] """The unique ID of the conversation.""" ================================================ FILE: src/openai/types/responses/response_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List, Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from .tool_param import ToolParam from .response_includable import ResponseIncludable from .tool_choice_options import ToolChoiceOptions from .response_input_param import ResponseInputParam from .response_prompt_param import ResponsePromptParam from .tool_choice_mcp_param import ToolChoiceMcpParam from ..shared_params.metadata import Metadata from .tool_choice_shell_param import ToolChoiceShellParam from .tool_choice_types_param import ToolChoiceTypesParam from ..shared_params.reasoning import Reasoning from .tool_choice_custom_param import ToolChoiceCustomParam from .tool_choice_allowed_param import ToolChoiceAllowedParam from .response_text_config_param import ResponseTextConfigParam from .tool_choice_function_param import ToolChoiceFunctionParam from .tool_choice_apply_patch_param import ToolChoiceApplyPatchParam from ..shared_params.responses_model import ResponsesModel from .response_conversation_param_param import ResponseConversationParamParam __all__ = [ "ResponseCreateParamsBase", "ContextManagement", "Conversation", "StreamOptions", "ToolChoice", "ResponseCreateParamsNonStreaming", "ResponseCreateParamsStreaming", ] class ResponseCreateParamsBase(TypedDict, total=False): background: Optional[bool] """ Whether to run the model response in the background. [Learn more](https://platform.openai.com/docs/guides/background). """ context_management: Optional[Iterable[ContextManagement]] """Context management configuration for this request.""" conversation: Optional[Conversation] """The conversation that this response belongs to. Items from this conversation are prepended to `input_items` for this response request. Input items and output items from this response are automatically added to this conversation after this response completes. """ include: Optional[List[ResponseIncludable]] """Specify additional output data to include in the model response. Currently supported values are: - `web_search_call.action.sources`: Include the sources of the web search tool call. - `code_interpreter_call.outputs`: Includes the outputs of python code execution in code interpreter tool call items. - `computer_call_output.output.image_url`: Include image urls from the computer call output. - `file_search_call.results`: Include the search results of the file search tool call. - `message.input_image.image_url`: Include image urls from the input message. - `message.output_text.logprobs`: Include logprobs with assistant messages. - `reasoning.encrypted_content`: Includes an encrypted version of reasoning tokens in reasoning item outputs. This enables reasoning items to be used in multi-turn conversations when using the Responses API statelessly (like when the `store` parameter is set to `false`, or when an organization is enrolled in the zero data retention program). """ input: Union[str, ResponseInputParam] """Text, image, or file inputs to the model, used to generate a response. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Image inputs](https://platform.openai.com/docs/guides/images) - [File inputs](https://platform.openai.com/docs/guides/pdf-files) - [Conversation state](https://platform.openai.com/docs/guides/conversation-state) - [Function calling](https://platform.openai.com/docs/guides/function-calling) """ instructions: Optional[str] """A system (or developer) message inserted into the model's context. When using along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses. """ max_output_tokens: Optional[int] """ An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). """ max_tool_calls: Optional[int] """ The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored. """ metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ model: ResponsesModel """Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. """ parallel_tool_calls: Optional[bool] """Whether to allow the model to run tool calls in parallel.""" previous_response_id: Optional[str] """The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://platform.openai.com/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`. """ prompt: Optional[ResponsePromptParam] """ Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). """ prompt_cache_key: str """ Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://platform.openai.com/docs/guides/prompt-caching). """ prompt_cache_retention: Optional[Literal["in-memory", "24h"]] """The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). """ reasoning: Optional[Reasoning] """**gpt-5 and o-series models only** Configuration options for [reasoning models](https://platform.openai.com/docs/guides/reasoning). """ safety_identifier: str """ A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). """ service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] """Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier. - When not set, the default behavior is 'auto'. When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. """ store: Optional[bool] """Whether to store the generated model response for later retrieval via API.""" stream_options: Optional[StreamOptions] """Options for streaming responses. Only set this when you set `stream: true`.""" temperature: Optional[float] """What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. """ text: ResponseTextConfigParam """Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) """ tool_choice: ToolChoice """ How the model should select which tool (or tools) to use when generating a response. See the `tools` parameter to see how to specify which tools the model can call. """ tools: Iterable[ToolParam] """An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. We support the following categories of tools: - **Built-in tools**: Tools that are provided by OpenAI that extend the model's capabilities, like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). - **MCP Tools**: Integrations with third-party systems via custom MCP servers or predefined connectors such as Google Drive and SharePoint. Learn more about [MCP Tools](https://platform.openai.com/docs/guides/tools-connectors-mcp). - **Function calls (custom tools)**: Functions that are defined by you, enabling the model to call your own code with strongly typed arguments and outputs. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). You can also use custom tools to call your own code. """ top_logprobs: Optional[int] """ An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. """ top_p: Optional[float] """ An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. """ truncation: Optional[Literal["auto", "disabled"]] """The truncation strategy to use for the model response. - `auto`: If the input to this Response exceeds the model's context window size, the model will truncate the response to fit the context window by dropping items from the beginning of the conversation. - `disabled` (default): If the input size will exceed the context window size for a model, the request will fail with a 400 error. """ user: str """This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations. A stable identifier for your end-users. Used to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). """ class ContextManagement(TypedDict, total=False): type: Required[str] """The context management entry type. Currently only 'compaction' is supported.""" compact_threshold: Optional[int] """Token threshold at which compaction should be triggered for this entry.""" Conversation: TypeAlias = Union[str, ResponseConversationParamParam] class StreamOptions(TypedDict, total=False): """Options for streaming responses. Only set this when you set `stream: true`.""" include_obfuscation: bool """When true, stream obfuscation will be enabled. Stream obfuscation adds random characters to an `obfuscation` field on streaming delta events to normalize payload sizes as a mitigation to certain side-channel attacks. These obfuscation fields are included by default, but add a small amount of overhead to the data stream. You can set `include_obfuscation` to false to optimize for bandwidth if you trust the network links between your application and the OpenAI API. """ ToolChoice: TypeAlias = Union[ ToolChoiceOptions, ToolChoiceAllowedParam, ToolChoiceTypesParam, ToolChoiceFunctionParam, ToolChoiceMcpParam, ToolChoiceCustomParam, ToolChoiceApplyPatchParam, ToolChoiceShellParam, ] class ResponseCreateParamsNonStreaming(ResponseCreateParamsBase, total=False): stream: Optional[Literal[False]] """ If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) for more information. """ class ResponseCreateParamsStreaming(ResponseCreateParamsBase): stream: Required[Literal[True]] """ If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) for more information. """ ResponseCreateParams = Union[ResponseCreateParamsNonStreaming, ResponseCreateParamsStreaming] ================================================ FILE: src/openai/types/responses/response_created_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .response import Response from ..._models import BaseModel __all__ = ["ResponseCreatedEvent"] class ResponseCreatedEvent(BaseModel): """An event that is emitted when a response is created.""" response: Response """The response that was created.""" sequence_number: int """The sequence number for this event.""" type: Literal["response.created"] """The type of the event. Always `response.created`.""" ================================================ FILE: src/openai/types/responses/response_custom_tool_call.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseCustomToolCall"] class ResponseCustomToolCall(BaseModel): """A call to a custom tool created by the model.""" call_id: str """An identifier used to map this custom tool call to a tool call output.""" input: str """The input for the custom tool call generated by the model.""" name: str """The name of the custom tool being called.""" type: Literal["custom_tool_call"] """The type of the custom tool call. Always `custom_tool_call`.""" id: Optional[str] = None """The unique ID of the custom tool call in the OpenAI platform.""" namespace: Optional[str] = None """The namespace of the custom tool being called.""" ================================================ FILE: src/openai/types/responses/response_custom_tool_call_input_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseCustomToolCallInputDeltaEvent"] class ResponseCustomToolCallInputDeltaEvent(BaseModel): """Event representing a delta (partial update) to the input of a custom tool call.""" delta: str """The incremental input data (delta) for the custom tool call.""" item_id: str """Unique identifier for the API item associated with this event.""" output_index: int """The index of the output this delta applies to.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.custom_tool_call_input.delta"] """The event type identifier.""" ================================================ FILE: src/openai/types/responses/response_custom_tool_call_input_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseCustomToolCallInputDoneEvent"] class ResponseCustomToolCallInputDoneEvent(BaseModel): """Event indicating that input for a custom tool call is complete.""" input: str """The complete input data for the custom tool call.""" item_id: str """Unique identifier for the API item associated with this event.""" output_index: int """The index of the output this event applies to.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.custom_tool_call_input.done"] """The event type identifier.""" ================================================ FILE: src/openai/types/responses/response_custom_tool_call_output.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .response_input_file import ResponseInputFile from .response_input_text import ResponseInputText from .response_input_image import ResponseInputImage __all__ = ["ResponseCustomToolCallOutput", "OutputOutputContentList"] OutputOutputContentList: TypeAlias = Annotated[ Union[ResponseInputText, ResponseInputImage, ResponseInputFile], PropertyInfo(discriminator="type") ] class ResponseCustomToolCallOutput(BaseModel): """The output of a custom tool call from your code, being sent back to the model.""" call_id: str """The call ID, used to map this custom tool call output to a custom tool call.""" output: Union[str, List[OutputOutputContentList]] """ The output from the custom tool call generated by your code. Can be a string or an list of output content. """ type: Literal["custom_tool_call_output"] """The type of the custom tool call output. Always `custom_tool_call_output`.""" id: Optional[str] = None """The unique ID of the custom tool call output in the OpenAI platform.""" ================================================ FILE: src/openai/types/responses/response_custom_tool_call_output_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable from typing_extensions import Literal, Required, TypeAlias, TypedDict from .response_input_file_param import ResponseInputFileParam from .response_input_text_param import ResponseInputTextParam from .response_input_image_param import ResponseInputImageParam __all__ = ["ResponseCustomToolCallOutputParam", "OutputOutputContentList"] OutputOutputContentList: TypeAlias = Union[ResponseInputTextParam, ResponseInputImageParam, ResponseInputFileParam] class ResponseCustomToolCallOutputParam(TypedDict, total=False): """The output of a custom tool call from your code, being sent back to the model.""" call_id: Required[str] """The call ID, used to map this custom tool call output to a custom tool call.""" output: Required[Union[str, Iterable[OutputOutputContentList]]] """ The output from the custom tool call generated by your code. Can be a string or an list of output content. """ type: Required[Literal["custom_tool_call_output"]] """The type of the custom tool call output. Always `custom_tool_call_output`.""" id: str """The unique ID of the custom tool call output in the OpenAI platform.""" ================================================ FILE: src/openai/types/responses/response_custom_tool_call_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ResponseCustomToolCallParam"] class ResponseCustomToolCallParam(TypedDict, total=False): """A call to a custom tool created by the model.""" call_id: Required[str] """An identifier used to map this custom tool call to a tool call output.""" input: Required[str] """The input for the custom tool call generated by the model.""" name: Required[str] """The name of the custom tool being called.""" type: Required[Literal["custom_tool_call"]] """The type of the custom tool call. Always `custom_tool_call`.""" id: str """The unique ID of the custom tool call in the OpenAI platform.""" namespace: str """The namespace of the custom tool being called.""" ================================================ FILE: src/openai/types/responses/response_error.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseError"] class ResponseError(BaseModel): """An error object returned when the model fails to generate a Response.""" code: Literal[ "server_error", "rate_limit_exceeded", "invalid_prompt", "vector_store_timeout", "invalid_image", "invalid_image_format", "invalid_base64_image", "invalid_image_url", "image_too_large", "image_too_small", "image_parse_error", "image_content_policy_violation", "invalid_image_mode", "image_file_too_large", "unsupported_image_media_type", "empty_image_file", "failed_to_download_image", "image_file_not_found", ] """The error code for the response.""" message: str """A human-readable description of the error.""" ================================================ FILE: src/openai/types/responses/response_error_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseErrorEvent"] class ResponseErrorEvent(BaseModel): """Emitted when an error occurs.""" code: Optional[str] = None """The error code.""" message: str """The error message.""" param: Optional[str] = None """The error parameter.""" sequence_number: int """The sequence number of this event.""" type: Literal["error"] """The type of the event. Always `error`.""" ================================================ FILE: src/openai/types/responses/response_failed_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .response import Response from ..._models import BaseModel __all__ = ["ResponseFailedEvent"] class ResponseFailedEvent(BaseModel): """An event that is emitted when a response fails.""" response: Response """The response that failed.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.failed"] """The type of the event. Always `response.failed`.""" ================================================ FILE: src/openai/types/responses/response_file_search_call_completed_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseFileSearchCallCompletedEvent"] class ResponseFileSearchCallCompletedEvent(BaseModel): """Emitted when a file search call is completed (results found).""" item_id: str """The ID of the output item that the file search call is initiated.""" output_index: int """The index of the output item that the file search call is initiated.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.file_search_call.completed"] """The type of the event. Always `response.file_search_call.completed`.""" ================================================ FILE: src/openai/types/responses/response_file_search_call_in_progress_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseFileSearchCallInProgressEvent"] class ResponseFileSearchCallInProgressEvent(BaseModel): """Emitted when a file search call is initiated.""" item_id: str """The ID of the output item that the file search call is initiated.""" output_index: int """The index of the output item that the file search call is initiated.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.file_search_call.in_progress"] """The type of the event. Always `response.file_search_call.in_progress`.""" ================================================ FILE: src/openai/types/responses/response_file_search_call_searching_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseFileSearchCallSearchingEvent"] class ResponseFileSearchCallSearchingEvent(BaseModel): """Emitted when a file search is currently searching.""" item_id: str """The ID of the output item that the file search call is initiated.""" output_index: int """The index of the output item that the file search call is searching.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.file_search_call.searching"] """The type of the event. Always `response.file_search_call.searching`.""" ================================================ FILE: src/openai/types/responses/response_file_search_tool_call.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseFileSearchToolCall", "Result"] class Result(BaseModel): attributes: Optional[Dict[str, Union[str, float, bool]]] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters, booleans, or numbers. """ file_id: Optional[str] = None """The unique ID of the file.""" filename: Optional[str] = None """The name of the file.""" score: Optional[float] = None """The relevance score of the file - a value between 0 and 1.""" text: Optional[str] = None """The text that was retrieved from the file.""" class ResponseFileSearchToolCall(BaseModel): """The results of a file search tool call. See the [file search guide](https://platform.openai.com/docs/guides/tools-file-search) for more information. """ id: str """The unique ID of the file search tool call.""" queries: List[str] """The queries used to search for files.""" status: Literal["in_progress", "searching", "completed", "incomplete", "failed"] """The status of the file search tool call. One of `in_progress`, `searching`, `incomplete` or `failed`, """ type: Literal["file_search_call"] """The type of the file search tool call. Always `file_search_call`.""" results: Optional[List[Result]] = None """The results of the file search tool call.""" ================================================ FILE: src/openai/types/responses/response_file_search_tool_call_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Union, Iterable, Optional from typing_extensions import Literal, Required, TypedDict from ..._types import SequenceNotStr __all__ = ["ResponseFileSearchToolCallParam", "Result"] class Result(TypedDict, total=False): attributes: Optional[Dict[str, Union[str, float, bool]]] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters, booleans, or numbers. """ file_id: str """The unique ID of the file.""" filename: str """The name of the file.""" score: float """The relevance score of the file - a value between 0 and 1.""" text: str """The text that was retrieved from the file.""" class ResponseFileSearchToolCallParam(TypedDict, total=False): """The results of a file search tool call. See the [file search guide](https://platform.openai.com/docs/guides/tools-file-search) for more information. """ id: Required[str] """The unique ID of the file search tool call.""" queries: Required[SequenceNotStr[str]] """The queries used to search for files.""" status: Required[Literal["in_progress", "searching", "completed", "incomplete", "failed"]] """The status of the file search tool call. One of `in_progress`, `searching`, `incomplete` or `failed`, """ type: Required[Literal["file_search_call"]] """The type of the file search tool call. Always `file_search_call`.""" results: Optional[Iterable[Result]] """The results of the file search tool call.""" ================================================ FILE: src/openai/types/responses/response_format_text_config.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from ..._utils import PropertyInfo from ..shared.response_format_text import ResponseFormatText from ..shared.response_format_json_object import ResponseFormatJSONObject from .response_format_text_json_schema_config import ResponseFormatTextJSONSchemaConfig __all__ = ["ResponseFormatTextConfig"] ResponseFormatTextConfig: TypeAlias = Annotated[ Union[ResponseFormatText, ResponseFormatTextJSONSchemaConfig, ResponseFormatJSONObject], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/types/responses/response_format_text_config_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import TypeAlias from ..shared_params.response_format_text import ResponseFormatText from ..shared_params.response_format_json_object import ResponseFormatJSONObject from .response_format_text_json_schema_config_param import ResponseFormatTextJSONSchemaConfigParam __all__ = ["ResponseFormatTextConfigParam"] ResponseFormatTextConfigParam: TypeAlias = Union[ ResponseFormatText, ResponseFormatTextJSONSchemaConfigParam, ResponseFormatJSONObject ] ================================================ FILE: src/openai/types/responses/response_format_text_json_schema_config.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, Optional from typing_extensions import Literal from pydantic import Field as FieldInfo from ..._models import BaseModel __all__ = ["ResponseFormatTextJSONSchemaConfig"] class ResponseFormatTextJSONSchemaConfig(BaseModel): """JSON Schema response format. Used to generate structured JSON responses. Learn more about [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs). """ name: str """The name of the response format. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64. """ schema_: Dict[str, object] = FieldInfo(alias="schema") """ The schema for the response format, described as a JSON Schema object. Learn how to build JSON schemas [here](https://json-schema.org/). """ type: Literal["json_schema"] """The type of response format being defined. Always `json_schema`.""" description: Optional[str] = None """ A description of what the response format is for, used by the model to determine how to respond in the format. """ strict: Optional[bool] = None """ Whether to enable strict schema adherence when generating the output. If set to true, the model will always follow the exact schema defined in the `schema` field. Only a subset of JSON Schema is supported when `strict` is `true`. To learn more, read the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). """ ================================================ FILE: src/openai/types/responses/response_format_text_json_schema_config_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Optional from typing_extensions import Literal, Required, TypedDict __all__ = ["ResponseFormatTextJSONSchemaConfigParam"] class ResponseFormatTextJSONSchemaConfigParam(TypedDict, total=False): """JSON Schema response format. Used to generate structured JSON responses. Learn more about [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs). """ name: Required[str] """The name of the response format. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64. """ schema: Required[Dict[str, object]] """ The schema for the response format, described as a JSON Schema object. Learn how to build JSON schemas [here](https://json-schema.org/). """ type: Required[Literal["json_schema"]] """The type of response format being defined. Always `json_schema`.""" description: str """ A description of what the response format is for, used by the model to determine how to respond in the format. """ strict: Optional[bool] """ Whether to enable strict schema adherence when generating the output. If set to true, the model will always follow the exact schema defined in the `schema` field. Only a subset of JSON Schema is supported when `strict` is `true`. To learn more, read the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). """ ================================================ FILE: src/openai/types/responses/response_function_call_arguments_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseFunctionCallArgumentsDeltaEvent"] class ResponseFunctionCallArgumentsDeltaEvent(BaseModel): """Emitted when there is a partial function-call arguments delta.""" delta: str """The function-call arguments delta that is added.""" item_id: str """The ID of the output item that the function-call arguments delta is added to.""" output_index: int """ The index of the output item that the function-call arguments delta is added to. """ sequence_number: int """The sequence number of this event.""" type: Literal["response.function_call_arguments.delta"] """The type of the event. Always `response.function_call_arguments.delta`.""" ================================================ FILE: src/openai/types/responses/response_function_call_arguments_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseFunctionCallArgumentsDoneEvent"] class ResponseFunctionCallArgumentsDoneEvent(BaseModel): """Emitted when function-call arguments are finalized.""" arguments: str """The function-call arguments.""" item_id: str """The ID of the item.""" name: str """The name of the function that was called.""" output_index: int """The index of the output item.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.function_call_arguments.done"] ================================================ FILE: src/openai/types/responses/response_function_call_output_item.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from ..._utils import PropertyInfo from .response_input_file_content import ResponseInputFileContent from .response_input_text_content import ResponseInputTextContent from .response_input_image_content import ResponseInputImageContent __all__ = ["ResponseFunctionCallOutputItem"] ResponseFunctionCallOutputItem: TypeAlias = Annotated[ Union[ResponseInputTextContent, ResponseInputImageContent, ResponseInputFileContent], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/types/responses/response_function_call_output_item_list.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List from typing_extensions import TypeAlias from .response_function_call_output_item import ResponseFunctionCallOutputItem __all__ = ["ResponseFunctionCallOutputItemList"] ResponseFunctionCallOutputItemList: TypeAlias = List[ResponseFunctionCallOutputItem] ================================================ FILE: src/openai/types/responses/response_function_call_output_item_list_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List, Union from typing_extensions import TypeAlias from .response_input_file_content_param import ResponseInputFileContentParam from .response_input_text_content_param import ResponseInputTextContentParam from .response_input_image_content_param import ResponseInputImageContentParam __all__ = ["ResponseFunctionCallOutputItemListParam", "ResponseFunctionCallOutputItemParam"] ResponseFunctionCallOutputItemParam: TypeAlias = Union[ ResponseInputTextContentParam, ResponseInputImageContentParam, ResponseInputFileContentParam ] ResponseFunctionCallOutputItemListParam: TypeAlias = List[ResponseFunctionCallOutputItemParam] ================================================ FILE: src/openai/types/responses/response_function_call_output_item_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import TypeAlias from .response_input_file_content_param import ResponseInputFileContentParam from .response_input_text_content_param import ResponseInputTextContentParam from .response_input_image_content_param import ResponseInputImageContentParam __all__ = ["ResponseFunctionCallOutputItemParam"] ResponseFunctionCallOutputItemParam: TypeAlias = Union[ ResponseInputTextContentParam, ResponseInputImageContentParam, ResponseInputFileContentParam ] ================================================ FILE: src/openai/types/responses/response_function_shell_call_output_content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = ["ResponseFunctionShellCallOutputContent", "Outcome", "OutcomeTimeout", "OutcomeExit"] class OutcomeTimeout(BaseModel): """Indicates that the shell call exceeded its configured time limit.""" type: Literal["timeout"] """The outcome type. Always `timeout`.""" class OutcomeExit(BaseModel): """Indicates that the shell commands finished and returned an exit code.""" exit_code: int """The exit code returned by the shell process.""" type: Literal["exit"] """The outcome type. Always `exit`.""" Outcome: TypeAlias = Annotated[Union[OutcomeTimeout, OutcomeExit], PropertyInfo(discriminator="type")] class ResponseFunctionShellCallOutputContent(BaseModel): """Captured stdout and stderr for a portion of a shell tool call output.""" outcome: Outcome """The exit or timeout outcome associated with this shell call.""" stderr: str """Captured stderr output for the shell call.""" stdout: str """Captured stdout output for the shell call.""" ================================================ FILE: src/openai/types/responses/response_function_shell_call_output_content_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, Required, TypeAlias, TypedDict __all__ = ["ResponseFunctionShellCallOutputContentParam", "Outcome", "OutcomeTimeout", "OutcomeExit"] class OutcomeTimeout(TypedDict, total=False): """Indicates that the shell call exceeded its configured time limit.""" type: Required[Literal["timeout"]] """The outcome type. Always `timeout`.""" class OutcomeExit(TypedDict, total=False): """Indicates that the shell commands finished and returned an exit code.""" exit_code: Required[int] """The exit code returned by the shell process.""" type: Required[Literal["exit"]] """The outcome type. Always `exit`.""" Outcome: TypeAlias = Union[OutcomeTimeout, OutcomeExit] class ResponseFunctionShellCallOutputContentParam(TypedDict, total=False): """Captured stdout and stderr for a portion of a shell tool call output.""" outcome: Required[Outcome] """The exit or timeout outcome associated with this shell call.""" stderr: Required[str] """Captured stderr output for the shell call.""" stdout: Required[str] """Captured stdout output for the shell call.""" ================================================ FILE: src/openai/types/responses/response_function_shell_tool_call.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .response_local_environment import ResponseLocalEnvironment from .response_container_reference import ResponseContainerReference __all__ = ["ResponseFunctionShellToolCall", "Action", "Environment"] class Action(BaseModel): """The shell commands and limits that describe how to run the tool call.""" commands: List[str] max_output_length: Optional[int] = None """Optional maximum number of characters to return from each command.""" timeout_ms: Optional[int] = None """Optional timeout in milliseconds for the commands.""" Environment: TypeAlias = Annotated[ Union[ResponseLocalEnvironment, ResponseContainerReference, None], PropertyInfo(discriminator="type") ] class ResponseFunctionShellToolCall(BaseModel): """A tool call that executes one or more shell commands in a managed environment.""" id: str """The unique ID of the shell tool call. Populated when this item is returned via API. """ action: Action """The shell commands and limits that describe how to run the tool call.""" call_id: str """The unique ID of the shell tool call generated by the model.""" environment: Optional[Environment] = None """Represents the use of a local environment to perform shell actions.""" status: Literal["in_progress", "completed", "incomplete"] """The status of the shell call. One of `in_progress`, `completed`, or `incomplete`. """ type: Literal["shell_call"] """The type of the item. Always `shell_call`.""" created_by: Optional[str] = None """The ID of the entity that created this tool call.""" ================================================ FILE: src/openai/types/responses/response_function_shell_tool_call_output.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = [ "ResponseFunctionShellToolCallOutput", "Output", "OutputOutcome", "OutputOutcomeTimeout", "OutputOutcomeExit", ] class OutputOutcomeTimeout(BaseModel): """Indicates that the shell call exceeded its configured time limit.""" type: Literal["timeout"] """The outcome type. Always `timeout`.""" class OutputOutcomeExit(BaseModel): """Indicates that the shell commands finished and returned an exit code.""" exit_code: int """Exit code from the shell process.""" type: Literal["exit"] """The outcome type. Always `exit`.""" OutputOutcome: TypeAlias = Annotated[Union[OutputOutcomeTimeout, OutputOutcomeExit], PropertyInfo(discriminator="type")] class Output(BaseModel): """The content of a shell tool call output that was emitted.""" outcome: OutputOutcome """ Represents either an exit outcome (with an exit code) or a timeout outcome for a shell call output chunk. """ stderr: str """The standard error output that was captured.""" stdout: str """The standard output that was captured.""" created_by: Optional[str] = None """The identifier of the actor that created the item.""" class ResponseFunctionShellToolCallOutput(BaseModel): """The output of a shell tool call that was emitted.""" id: str """The unique ID of the shell call output. Populated when this item is returned via API. """ call_id: str """The unique ID of the shell tool call generated by the model.""" max_output_length: Optional[int] = None """The maximum length of the shell command output. This is generated by the model and should be passed back with the raw output. """ output: List[Output] """An array of shell call output contents""" status: Literal["in_progress", "completed", "incomplete"] """The status of the shell call output. One of `in_progress`, `completed`, or `incomplete`. """ type: Literal["shell_call_output"] """The type of the shell call output. Always `shell_call_output`.""" created_by: Optional[str] = None """The identifier of the actor that created the item.""" ================================================ FILE: src/openai/types/responses/response_function_tool_call.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseFunctionToolCall"] class ResponseFunctionToolCall(BaseModel): """A tool call to run a function. See the [function calling guide](https://platform.openai.com/docs/guides/function-calling) for more information. """ arguments: str """A JSON string of the arguments to pass to the function.""" call_id: str """The unique ID of the function tool call generated by the model.""" name: str """The name of the function to run.""" type: Literal["function_call"] """The type of the function tool call. Always `function_call`.""" id: Optional[str] = None """The unique ID of the function tool call.""" namespace: Optional[str] = None """The namespace of the function to run.""" status: Optional[Literal["in_progress", "completed", "incomplete"]] = None """The status of the item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API. """ ================================================ FILE: src/openai/types/responses/response_function_tool_call_item.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .response_function_tool_call import ResponseFunctionToolCall __all__ = ["ResponseFunctionToolCallItem"] class ResponseFunctionToolCallItem(ResponseFunctionToolCall): """A tool call to run a function. See the [function calling guide](https://platform.openai.com/docs/guides/function-calling) for more information. """ id: str # type: ignore """The unique ID of the function tool call.""" ================================================ FILE: src/openai/types/responses/response_function_tool_call_output_item.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .response_input_file import ResponseInputFile from .response_input_text import ResponseInputText from .response_input_image import ResponseInputImage __all__ = ["ResponseFunctionToolCallOutputItem", "OutputOutputContentList"] OutputOutputContentList: TypeAlias = Annotated[ Union[ResponseInputText, ResponseInputImage, ResponseInputFile], PropertyInfo(discriminator="type") ] class ResponseFunctionToolCallOutputItem(BaseModel): id: str """The unique ID of the function call tool output.""" call_id: str """The unique ID of the function tool call generated by the model.""" output: Union[str, List[OutputOutputContentList]] """ The output from the function call generated by your code. Can be a string or an list of output content. """ type: Literal["function_call_output"] """The type of the function tool call output. Always `function_call_output`.""" status: Optional[Literal["in_progress", "completed", "incomplete"]] = None """The status of the item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API. """ ================================================ FILE: src/openai/types/responses/response_function_tool_call_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ResponseFunctionToolCallParam"] class ResponseFunctionToolCallParam(TypedDict, total=False): """A tool call to run a function. See the [function calling guide](https://platform.openai.com/docs/guides/function-calling) for more information. """ arguments: Required[str] """A JSON string of the arguments to pass to the function.""" call_id: Required[str] """The unique ID of the function tool call generated by the model.""" name: Required[str] """The name of the function to run.""" type: Required[Literal["function_call"]] """The type of the function tool call. Always `function_call`.""" id: str """The unique ID of the function tool call.""" namespace: str """The namespace of the function to run.""" status: Literal["in_progress", "completed", "incomplete"] """The status of the item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API. """ ================================================ FILE: src/openai/types/responses/response_function_web_search.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = [ "ResponseFunctionWebSearch", "Action", "ActionSearch", "ActionSearchSource", "ActionOpenPage", "ActionFind", ] class ActionSearchSource(BaseModel): """A source used in the search.""" type: Literal["url"] """The type of source. Always `url`.""" url: str """The URL of the source.""" class ActionSearch(BaseModel): """Action type "search" - Performs a web search query.""" query: str """[DEPRECATED] The search query.""" type: Literal["search"] """The action type.""" queries: Optional[List[str]] = None """The search queries.""" sources: Optional[List[ActionSearchSource]] = None """The sources used in the search.""" class ActionOpenPage(BaseModel): """Action type "open_page" - Opens a specific URL from search results.""" type: Literal["open_page"] """The action type.""" url: Optional[str] = None """The URL opened by the model.""" class ActionFind(BaseModel): """Action type "find_in_page": Searches for a pattern within a loaded page.""" pattern: str """The pattern or text to search for within the page.""" type: Literal["find_in_page"] """The action type.""" url: str """The URL of the page searched for the pattern.""" Action: TypeAlias = Annotated[Union[ActionSearch, ActionOpenPage, ActionFind], PropertyInfo(discriminator="type")] class ResponseFunctionWebSearch(BaseModel): """The results of a web search tool call. See the [web search guide](https://platform.openai.com/docs/guides/tools-web-search) for more information. """ id: str """The unique ID of the web search tool call.""" action: Action """ An object describing the specific action taken in this web search call. Includes details on how the model used the web (search, open_page, find_in_page). """ status: Literal["in_progress", "searching", "completed", "failed"] """The status of the web search tool call.""" type: Literal["web_search_call"] """The type of the web search tool call. Always `web_search_call`.""" ================================================ FILE: src/openai/types/responses/response_function_web_search_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import SequenceNotStr __all__ = [ "ResponseFunctionWebSearchParam", "Action", "ActionSearch", "ActionSearchSource", "ActionOpenPage", "ActionFind", ] class ActionSearchSource(TypedDict, total=False): """A source used in the search.""" type: Required[Literal["url"]] """The type of source. Always `url`.""" url: Required[str] """The URL of the source.""" class ActionSearch(TypedDict, total=False): """Action type "search" - Performs a web search query.""" query: Required[str] """[DEPRECATED] The search query.""" type: Required[Literal["search"]] """The action type.""" queries: SequenceNotStr[str] """The search queries.""" sources: Iterable[ActionSearchSource] """The sources used in the search.""" class ActionOpenPage(TypedDict, total=False): """Action type "open_page" - Opens a specific URL from search results.""" type: Required[Literal["open_page"]] """The action type.""" url: Optional[str] """The URL opened by the model.""" class ActionFind(TypedDict, total=False): """Action type "find_in_page": Searches for a pattern within a loaded page.""" pattern: Required[str] """The pattern or text to search for within the page.""" type: Required[Literal["find_in_page"]] """The action type.""" url: Required[str] """The URL of the page searched for the pattern.""" Action: TypeAlias = Union[ActionSearch, ActionOpenPage, ActionFind] class ResponseFunctionWebSearchParam(TypedDict, total=False): """The results of a web search tool call. See the [web search guide](https://platform.openai.com/docs/guides/tools-web-search) for more information. """ id: Required[str] """The unique ID of the web search tool call.""" action: Required[Action] """ An object describing the specific action taken in this web search call. Includes details on how the model used the web (search, open_page, find_in_page). """ status: Required[Literal["in_progress", "searching", "completed", "failed"]] """The status of the web search tool call.""" type: Required[Literal["web_search_call"]] """The type of the web search tool call. Always `web_search_call`.""" ================================================ FILE: src/openai/types/responses/response_image_gen_call_completed_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseImageGenCallCompletedEvent"] class ResponseImageGenCallCompletedEvent(BaseModel): """ Emitted when an image generation tool call has completed and the final image is available. """ item_id: str """The unique identifier of the image generation item being processed.""" output_index: int """The index of the output item in the response's output array.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.image_generation_call.completed"] """The type of the event. Always 'response.image_generation_call.completed'.""" ================================================ FILE: src/openai/types/responses/response_image_gen_call_generating_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseImageGenCallGeneratingEvent"] class ResponseImageGenCallGeneratingEvent(BaseModel): """ Emitted when an image generation tool call is actively generating an image (intermediate state). """ item_id: str """The unique identifier of the image generation item being processed.""" output_index: int """The index of the output item in the response's output array.""" sequence_number: int """The sequence number of the image generation item being processed.""" type: Literal["response.image_generation_call.generating"] """The type of the event. Always 'response.image_generation_call.generating'.""" ================================================ FILE: src/openai/types/responses/response_image_gen_call_in_progress_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseImageGenCallInProgressEvent"] class ResponseImageGenCallInProgressEvent(BaseModel): """Emitted when an image generation tool call is in progress.""" item_id: str """The unique identifier of the image generation item being processed.""" output_index: int """The index of the output item in the response's output array.""" sequence_number: int """The sequence number of the image generation item being processed.""" type: Literal["response.image_generation_call.in_progress"] """The type of the event. Always 'response.image_generation_call.in_progress'.""" ================================================ FILE: src/openai/types/responses/response_image_gen_call_partial_image_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseImageGenCallPartialImageEvent"] class ResponseImageGenCallPartialImageEvent(BaseModel): """Emitted when a partial image is available during image generation streaming.""" item_id: str """The unique identifier of the image generation item being processed.""" output_index: int """The index of the output item in the response's output array.""" partial_image_b64: str """Base64-encoded partial image data, suitable for rendering as an image.""" partial_image_index: int """ 0-based index for the partial image (backend is 1-based, but this is 0-based for the user). """ sequence_number: int """The sequence number of the image generation item being processed.""" type: Literal["response.image_generation_call.partial_image"] """The type of the event. Always 'response.image_generation_call.partial_image'.""" ================================================ FILE: src/openai/types/responses/response_in_progress_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .response import Response from ..._models import BaseModel __all__ = ["ResponseInProgressEvent"] class ResponseInProgressEvent(BaseModel): """Emitted when the response is in progress.""" response: Response """The response that is in progress.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.in_progress"] """The type of the event. Always `response.in_progress`.""" ================================================ FILE: src/openai/types/responses/response_includable.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["ResponseIncludable"] ResponseIncludable: TypeAlias = Literal[ "file_search_call.results", "web_search_call.results", "web_search_call.action.sources", "message.input_image.image_url", "computer_call_output.output.image_url", "code_interpreter_call.outputs", "reasoning.encrypted_content", "message.output_text.logprobs", ] ================================================ FILE: src/openai/types/responses/response_incomplete_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .response import Response from ..._models import BaseModel __all__ = ["ResponseIncompleteEvent"] class ResponseIncompleteEvent(BaseModel): """An event that is emitted when a response finishes as incomplete.""" response: Response """The response that was incomplete.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.incomplete"] """The type of the event. Always `response.incomplete`.""" ================================================ FILE: src/openai/types/responses/response_input.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List from typing_extensions import TypeAlias from .response_input_item import ResponseInputItem __all__ = ["ResponseInput"] ResponseInput: TypeAlias = List[ResponseInputItem] ================================================ FILE: src/openai/types/responses/response_input_audio.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseInputAudio", "InputAudio"] class InputAudio(BaseModel): data: str """Base64-encoded audio data.""" format: Literal["mp3", "wav"] """The format of the audio data. Currently supported formats are `mp3` and `wav`.""" class ResponseInputAudio(BaseModel): """An audio input to the model.""" input_audio: InputAudio type: Literal["input_audio"] """The type of the input item. Always `input_audio`.""" ================================================ FILE: src/openai/types/responses/response_input_audio_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ResponseInputAudioParam", "InputAudio"] class InputAudio(TypedDict, total=False): data: Required[str] """Base64-encoded audio data.""" format: Required[Literal["mp3", "wav"]] """The format of the audio data. Currently supported formats are `mp3` and `wav`.""" class ResponseInputAudioParam(TypedDict, total=False): """An audio input to the model.""" input_audio: Required[InputAudio] type: Required[Literal["input_audio"]] """The type of the input item. Always `input_audio`.""" ================================================ FILE: src/openai/types/responses/response_input_content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from ..._utils import PropertyInfo from .response_input_file import ResponseInputFile from .response_input_text import ResponseInputText from .response_input_image import ResponseInputImage __all__ = ["ResponseInputContent"] ResponseInputContent: TypeAlias = Annotated[ Union[ResponseInputText, ResponseInputImage, ResponseInputFile], PropertyInfo(discriminator="type") ] ================================================ FILE: src/openai/types/responses/response_input_content_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import TypeAlias from .response_input_file_param import ResponseInputFileParam from .response_input_text_param import ResponseInputTextParam from .response_input_image_param import ResponseInputImageParam __all__ = ["ResponseInputContentParam"] ResponseInputContentParam: TypeAlias = Union[ResponseInputTextParam, ResponseInputImageParam, ResponseInputFileParam] ================================================ FILE: src/openai/types/responses/response_input_file.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseInputFile"] class ResponseInputFile(BaseModel): """A file input to the model.""" type: Literal["input_file"] """The type of the input item. Always `input_file`.""" file_data: Optional[str] = None """The content of the file to be sent to the model.""" file_id: Optional[str] = None """The ID of the file to be sent to the model.""" file_url: Optional[str] = None """The URL of the file to be sent to the model.""" filename: Optional[str] = None """The name of the file to be sent to the model.""" ================================================ FILE: src/openai/types/responses/response_input_file_content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseInputFileContent"] class ResponseInputFileContent(BaseModel): """A file input to the model.""" type: Literal["input_file"] """The type of the input item. Always `input_file`.""" file_data: Optional[str] = None """The base64-encoded data of the file to be sent to the model.""" file_id: Optional[str] = None """The ID of the file to be sent to the model.""" file_url: Optional[str] = None """The URL of the file to be sent to the model.""" filename: Optional[str] = None """The name of the file to be sent to the model.""" ================================================ FILE: src/openai/types/responses/response_input_file_content_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Literal, Required, TypedDict __all__ = ["ResponseInputFileContentParam"] class ResponseInputFileContentParam(TypedDict, total=False): """A file input to the model.""" type: Required[Literal["input_file"]] """The type of the input item. Always `input_file`.""" file_data: Optional[str] """The base64-encoded data of the file to be sent to the model.""" file_id: Optional[str] """The ID of the file to be sent to the model.""" file_url: Optional[str] """The URL of the file to be sent to the model.""" filename: Optional[str] """The name of the file to be sent to the model.""" ================================================ FILE: src/openai/types/responses/response_input_file_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Literal, Required, TypedDict __all__ = ["ResponseInputFileParam"] class ResponseInputFileParam(TypedDict, total=False): """A file input to the model.""" type: Required[Literal["input_file"]] """The type of the input item. Always `input_file`.""" file_data: str """The content of the file to be sent to the model.""" file_id: Optional[str] """The ID of the file to be sent to the model.""" file_url: str """The URL of the file to be sent to the model.""" filename: str """The name of the file to be sent to the model.""" ================================================ FILE: src/openai/types/responses/response_input_image.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseInputImage"] class ResponseInputImage(BaseModel): """An image input to the model. Learn about [image inputs](https://platform.openai.com/docs/guides/vision). """ detail: Literal["low", "high", "auto", "original"] """The detail level of the image to be sent to the model. One of `high`, `low`, `auto`, or `original`. Defaults to `auto`. """ type: Literal["input_image"] """The type of the input item. Always `input_image`.""" file_id: Optional[str] = None """The ID of the file to be sent to the model.""" image_url: Optional[str] = None """The URL of the image to be sent to the model. A fully qualified URL or base64 encoded image in a data URL. """ ================================================ FILE: src/openai/types/responses/response_input_image_content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseInputImageContent"] class ResponseInputImageContent(BaseModel): """An image input to the model. Learn about [image inputs](https://platform.openai.com/docs/guides/vision) """ type: Literal["input_image"] """The type of the input item. Always `input_image`.""" detail: Optional[Literal["low", "high", "auto", "original"]] = None """The detail level of the image to be sent to the model. One of `high`, `low`, `auto`, or `original`. Defaults to `auto`. """ file_id: Optional[str] = None """The ID of the file to be sent to the model.""" image_url: Optional[str] = None """The URL of the image to be sent to the model. A fully qualified URL or base64 encoded image in a data URL. """ ================================================ FILE: src/openai/types/responses/response_input_image_content_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Literal, Required, TypedDict __all__ = ["ResponseInputImageContentParam"] class ResponseInputImageContentParam(TypedDict, total=False): """An image input to the model. Learn about [image inputs](https://platform.openai.com/docs/guides/vision) """ type: Required[Literal["input_image"]] """The type of the input item. Always `input_image`.""" detail: Optional[Literal["low", "high", "auto", "original"]] """The detail level of the image to be sent to the model. One of `high`, `low`, `auto`, or `original`. Defaults to `auto`. """ file_id: Optional[str] """The ID of the file to be sent to the model.""" image_url: Optional[str] """The URL of the image to be sent to the model. A fully qualified URL or base64 encoded image in a data URL. """ ================================================ FILE: src/openai/types/responses/response_input_image_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Literal, Required, TypedDict __all__ = ["ResponseInputImageParam"] class ResponseInputImageParam(TypedDict, total=False): """An image input to the model. Learn about [image inputs](https://platform.openai.com/docs/guides/vision). """ detail: Required[Literal["low", "high", "auto", "original"]] """The detail level of the image to be sent to the model. One of `high`, `low`, `auto`, or `original`. Defaults to `auto`. """ type: Required[Literal["input_image"]] """The type of the input item. Always `input_image`.""" file_id: Optional[str] """The ID of the file to be sent to the model.""" image_url: Optional[str] """The URL of the image to be sent to the model. A fully qualified URL or base64 encoded image in a data URL. """ ================================================ FILE: src/openai/types/responses/response_input_item.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .local_environment import LocalEnvironment from .easy_input_message import EasyInputMessage from .container_reference import ContainerReference from .response_output_message import ResponseOutputMessage from .response_reasoning_item import ResponseReasoningItem from .response_custom_tool_call import ResponseCustomToolCall from .response_computer_tool_call import ResponseComputerToolCall from .response_function_tool_call import ResponseFunctionToolCall from .response_function_web_search import ResponseFunctionWebSearch from .response_compaction_item_param import ResponseCompactionItemParam from .response_file_search_tool_call import ResponseFileSearchToolCall from .response_custom_tool_call_output import ResponseCustomToolCallOutput from .response_code_interpreter_tool_call import ResponseCodeInterpreterToolCall from .response_input_message_content_list import ResponseInputMessageContentList from .response_tool_search_output_item_param import ResponseToolSearchOutputItemParam from .response_function_call_output_item_list import ResponseFunctionCallOutputItemList from .response_function_shell_call_output_content import ResponseFunctionShellCallOutputContent from .response_computer_tool_call_output_screenshot import ResponseComputerToolCallOutputScreenshot __all__ = [ "ResponseInputItem", "Message", "ComputerCallOutput", "ComputerCallOutputAcknowledgedSafetyCheck", "FunctionCallOutput", "ToolSearchCall", "ImageGenerationCall", "LocalShellCall", "LocalShellCallAction", "LocalShellCallOutput", "ShellCall", "ShellCallAction", "ShellCallEnvironment", "ShellCallOutput", "ApplyPatchCall", "ApplyPatchCallOperation", "ApplyPatchCallOperationCreateFile", "ApplyPatchCallOperationDeleteFile", "ApplyPatchCallOperationUpdateFile", "ApplyPatchCallOutput", "McpListTools", "McpListToolsTool", "McpApprovalRequest", "McpApprovalResponse", "McpCall", "ItemReference", ] class Message(BaseModel): """ A message input to the model with a role indicating instruction following hierarchy. Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role. """ content: ResponseInputMessageContentList """ A list of one or many input items to the model, containing different content types. """ role: Literal["user", "system", "developer"] """The role of the message input. One of `user`, `system`, or `developer`.""" status: Optional[Literal["in_progress", "completed", "incomplete"]] = None """The status of item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API. """ type: Optional[Literal["message"]] = None """The type of the message input. Always set to `message`.""" class ComputerCallOutputAcknowledgedSafetyCheck(BaseModel): """A pending safety check for the computer call.""" id: str """The ID of the pending safety check.""" code: Optional[str] = None """The type of the pending safety check.""" message: Optional[str] = None """Details about the pending safety check.""" class ComputerCallOutput(BaseModel): """The output of a computer tool call.""" call_id: str """The ID of the computer tool call that produced the output.""" output: ResponseComputerToolCallOutputScreenshot """A computer screenshot image used with the computer use tool.""" type: Literal["computer_call_output"] """The type of the computer tool call output. Always `computer_call_output`.""" id: Optional[str] = None """The ID of the computer tool call output.""" acknowledged_safety_checks: Optional[List[ComputerCallOutputAcknowledgedSafetyCheck]] = None """ The safety checks reported by the API that have been acknowledged by the developer. """ status: Optional[Literal["in_progress", "completed", "incomplete"]] = None """The status of the message input. One of `in_progress`, `completed`, or `incomplete`. Populated when input items are returned via API. """ class FunctionCallOutput(BaseModel): """The output of a function tool call.""" call_id: str """The unique ID of the function tool call generated by the model.""" output: Union[str, ResponseFunctionCallOutputItemList] """Text, image, or file output of the function tool call.""" type: Literal["function_call_output"] """The type of the function tool call output. Always `function_call_output`.""" id: Optional[str] = None """The unique ID of the function tool call output. Populated when this item is returned via API. """ status: Optional[Literal["in_progress", "completed", "incomplete"]] = None """The status of the item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API. """ class ToolSearchCall(BaseModel): arguments: object """The arguments supplied to the tool search call.""" type: Literal["tool_search_call"] """The item type. Always `tool_search_call`.""" id: Optional[str] = None """The unique ID of this tool search call.""" call_id: Optional[str] = None """The unique ID of the tool search call generated by the model.""" execution: Optional[Literal["server", "client"]] = None """Whether tool search was executed by the server or by the client.""" status: Optional[Literal["in_progress", "completed", "incomplete"]] = None """The status of the tool search call.""" class ImageGenerationCall(BaseModel): """An image generation request made by the model.""" id: str """The unique ID of the image generation call.""" result: Optional[str] = None """The generated image encoded in base64.""" status: Literal["in_progress", "completed", "generating", "failed"] """The status of the image generation call.""" type: Literal["image_generation_call"] """The type of the image generation call. Always `image_generation_call`.""" class LocalShellCallAction(BaseModel): """Execute a shell command on the server.""" command: List[str] """The command to run.""" env: Dict[str, str] """Environment variables to set for the command.""" type: Literal["exec"] """The type of the local shell action. Always `exec`.""" timeout_ms: Optional[int] = None """Optional timeout in milliseconds for the command.""" user: Optional[str] = None """Optional user to run the command as.""" working_directory: Optional[str] = None """Optional working directory to run the command in.""" class LocalShellCall(BaseModel): """A tool call to run a command on the local shell.""" id: str """The unique ID of the local shell call.""" action: LocalShellCallAction """Execute a shell command on the server.""" call_id: str """The unique ID of the local shell tool call generated by the model.""" status: Literal["in_progress", "completed", "incomplete"] """The status of the local shell call.""" type: Literal["local_shell_call"] """The type of the local shell call. Always `local_shell_call`.""" class LocalShellCallOutput(BaseModel): """The output of a local shell tool call.""" id: str """The unique ID of the local shell tool call generated by the model.""" output: str """A JSON string of the output of the local shell tool call.""" type: Literal["local_shell_call_output"] """The type of the local shell tool call output. Always `local_shell_call_output`.""" status: Optional[Literal["in_progress", "completed", "incomplete"]] = None """The status of the item. One of `in_progress`, `completed`, or `incomplete`.""" class ShellCallAction(BaseModel): """The shell commands and limits that describe how to run the tool call.""" commands: List[str] """Ordered shell commands for the execution environment to run.""" max_output_length: Optional[int] = None """ Maximum number of UTF-8 characters to capture from combined stdout and stderr output. """ timeout_ms: Optional[int] = None """Maximum wall-clock time in milliseconds to allow the shell commands to run.""" ShellCallEnvironment: TypeAlias = Annotated[ Union[LocalEnvironment, ContainerReference, None], PropertyInfo(discriminator="type") ] class ShellCall(BaseModel): """A tool representing a request to execute one or more shell commands.""" action: ShellCallAction """The shell commands and limits that describe how to run the tool call.""" call_id: str """The unique ID of the shell tool call generated by the model.""" type: Literal["shell_call"] """The type of the item. Always `shell_call`.""" id: Optional[str] = None """The unique ID of the shell tool call. Populated when this item is returned via API. """ environment: Optional[ShellCallEnvironment] = None """The environment to execute the shell commands in.""" status: Optional[Literal["in_progress", "completed", "incomplete"]] = None """The status of the shell call. One of `in_progress`, `completed`, or `incomplete`. """ class ShellCallOutput(BaseModel): """The streamed output items emitted by a shell tool call.""" call_id: str """The unique ID of the shell tool call generated by the model.""" output: List[ResponseFunctionShellCallOutputContent] """ Captured chunks of stdout and stderr output, along with their associated outcomes. """ type: Literal["shell_call_output"] """The type of the item. Always `shell_call_output`.""" id: Optional[str] = None """The unique ID of the shell tool call output. Populated when this item is returned via API. """ max_output_length: Optional[int] = None """ The maximum number of UTF-8 characters captured for this shell call's combined output. """ status: Optional[Literal["in_progress", "completed", "incomplete"]] = None """The status of the shell call output.""" class ApplyPatchCallOperationCreateFile(BaseModel): """Instruction for creating a new file via the apply_patch tool.""" diff: str """Unified diff content to apply when creating the file.""" path: str """Path of the file to create relative to the workspace root.""" type: Literal["create_file"] """The operation type. Always `create_file`.""" class ApplyPatchCallOperationDeleteFile(BaseModel): """Instruction for deleting an existing file via the apply_patch tool.""" path: str """Path of the file to delete relative to the workspace root.""" type: Literal["delete_file"] """The operation type. Always `delete_file`.""" class ApplyPatchCallOperationUpdateFile(BaseModel): """Instruction for updating an existing file via the apply_patch tool.""" diff: str """Unified diff content to apply to the existing file.""" path: str """Path of the file to update relative to the workspace root.""" type: Literal["update_file"] """The operation type. Always `update_file`.""" ApplyPatchCallOperation: TypeAlias = Annotated[ Union[ApplyPatchCallOperationCreateFile, ApplyPatchCallOperationDeleteFile, ApplyPatchCallOperationUpdateFile], PropertyInfo(discriminator="type"), ] class ApplyPatchCall(BaseModel): """ A tool call representing a request to create, delete, or update files using diff patches. """ call_id: str """The unique ID of the apply patch tool call generated by the model.""" operation: ApplyPatchCallOperation """ The specific create, delete, or update instruction for the apply_patch tool call. """ status: Literal["in_progress", "completed"] """The status of the apply patch tool call. One of `in_progress` or `completed`.""" type: Literal["apply_patch_call"] """The type of the item. Always `apply_patch_call`.""" id: Optional[str] = None """The unique ID of the apply patch tool call. Populated when this item is returned via API. """ class ApplyPatchCallOutput(BaseModel): """The streamed output emitted by an apply patch tool call.""" call_id: str """The unique ID of the apply patch tool call generated by the model.""" status: Literal["completed", "failed"] """The status of the apply patch tool call output. One of `completed` or `failed`.""" type: Literal["apply_patch_call_output"] """The type of the item. Always `apply_patch_call_output`.""" id: Optional[str] = None """The unique ID of the apply patch tool call output. Populated when this item is returned via API. """ output: Optional[str] = None """ Optional human-readable log text from the apply patch tool (e.g., patch results or errors). """ class McpListToolsTool(BaseModel): """A tool available on an MCP server.""" input_schema: object """The JSON schema describing the tool's input.""" name: str """The name of the tool.""" annotations: Optional[object] = None """Additional annotations about the tool.""" description: Optional[str] = None """The description of the tool.""" class McpListTools(BaseModel): """A list of tools available on an MCP server.""" id: str """The unique ID of the list.""" server_label: str """The label of the MCP server.""" tools: List[McpListToolsTool] """The tools available on the server.""" type: Literal["mcp_list_tools"] """The type of the item. Always `mcp_list_tools`.""" error: Optional[str] = None """Error message if the server could not list tools.""" class McpApprovalRequest(BaseModel): """A request for human approval of a tool invocation.""" id: str """The unique ID of the approval request.""" arguments: str """A JSON string of arguments for the tool.""" name: str """The name of the tool to run.""" server_label: str """The label of the MCP server making the request.""" type: Literal["mcp_approval_request"] """The type of the item. Always `mcp_approval_request`.""" class McpApprovalResponse(BaseModel): """A response to an MCP approval request.""" approval_request_id: str """The ID of the approval request being answered.""" approve: bool """Whether the request was approved.""" type: Literal["mcp_approval_response"] """The type of the item. Always `mcp_approval_response`.""" id: Optional[str] = None """The unique ID of the approval response""" reason: Optional[str] = None """Optional reason for the decision.""" class McpCall(BaseModel): """An invocation of a tool on an MCP server.""" id: str """The unique ID of the tool call.""" arguments: str """A JSON string of the arguments passed to the tool.""" name: str """The name of the tool that was run.""" server_label: str """The label of the MCP server running the tool.""" type: Literal["mcp_call"] """The type of the item. Always `mcp_call`.""" approval_request_id: Optional[str] = None """ Unique identifier for the MCP tool call approval request. Include this value in a subsequent `mcp_approval_response` input to approve or reject the corresponding tool call. """ error: Optional[str] = None """The error from the tool call, if any.""" output: Optional[str] = None """The output from the tool call.""" status: Optional[Literal["in_progress", "completed", "incomplete", "calling", "failed"]] = None """The status of the tool call. One of `in_progress`, `completed`, `incomplete`, `calling`, or `failed`. """ class ItemReference(BaseModel): """An internal identifier for an item to reference.""" id: str """The ID of the item to reference.""" type: Optional[Literal["item_reference"]] = None """The type of item to reference. Always `item_reference`.""" ResponseInputItem: TypeAlias = Annotated[ Union[ EasyInputMessage, Message, ResponseOutputMessage, ResponseFileSearchToolCall, ResponseComputerToolCall, ComputerCallOutput, ResponseFunctionWebSearch, ResponseFunctionToolCall, FunctionCallOutput, ToolSearchCall, ResponseToolSearchOutputItemParam, ResponseReasoningItem, ResponseCompactionItemParam, ImageGenerationCall, ResponseCodeInterpreterToolCall, LocalShellCall, LocalShellCallOutput, ShellCall, ShellCallOutput, ApplyPatchCall, ApplyPatchCallOutput, McpListTools, McpApprovalRequest, McpApprovalResponse, McpCall, ResponseCustomToolCallOutput, ResponseCustomToolCall, ItemReference, ], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/types/responses/response_input_item_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import SequenceNotStr from .local_environment_param import LocalEnvironmentParam from .easy_input_message_param import EasyInputMessageParam from .container_reference_param import ContainerReferenceParam from .response_output_message_param import ResponseOutputMessageParam from .response_reasoning_item_param import ResponseReasoningItemParam from .response_custom_tool_call_param import ResponseCustomToolCallParam from .response_computer_tool_call_param import ResponseComputerToolCallParam from .response_function_tool_call_param import ResponseFunctionToolCallParam from .response_function_web_search_param import ResponseFunctionWebSearchParam from .response_compaction_item_param_param import ResponseCompactionItemParamParam from .response_file_search_tool_call_param import ResponseFileSearchToolCallParam from .response_custom_tool_call_output_param import ResponseCustomToolCallOutputParam from .response_code_interpreter_tool_call_param import ResponseCodeInterpreterToolCallParam from .response_input_message_content_list_param import ResponseInputMessageContentListParam from .response_tool_search_output_item_param_param import ResponseToolSearchOutputItemParamParam from .response_function_call_output_item_list_param import ResponseFunctionCallOutputItemListParam from .response_function_shell_call_output_content_param import ResponseFunctionShellCallOutputContentParam from .response_computer_tool_call_output_screenshot_param import ResponseComputerToolCallOutputScreenshotParam __all__ = [ "ResponseInputItemParam", "Message", "ComputerCallOutput", "ComputerCallOutputAcknowledgedSafetyCheck", "FunctionCallOutput", "ToolSearchCall", "ImageGenerationCall", "LocalShellCall", "LocalShellCallAction", "LocalShellCallOutput", "ShellCall", "ShellCallAction", "ShellCallEnvironment", "ShellCallOutput", "ApplyPatchCall", "ApplyPatchCallOperation", "ApplyPatchCallOperationCreateFile", "ApplyPatchCallOperationDeleteFile", "ApplyPatchCallOperationUpdateFile", "ApplyPatchCallOutput", "McpListTools", "McpListToolsTool", "McpApprovalRequest", "McpApprovalResponse", "McpCall", "ItemReference", ] class Message(TypedDict, total=False): """ A message input to the model with a role indicating instruction following hierarchy. Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role. """ content: Required[ResponseInputMessageContentListParam] """ A list of one or many input items to the model, containing different content types. """ role: Required[Literal["user", "system", "developer"]] """The role of the message input. One of `user`, `system`, or `developer`.""" status: Literal["in_progress", "completed", "incomplete"] """The status of item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API. """ type: Literal["message"] """The type of the message input. Always set to `message`.""" class ComputerCallOutputAcknowledgedSafetyCheck(TypedDict, total=False): """A pending safety check for the computer call.""" id: Required[str] """The ID of the pending safety check.""" code: Optional[str] """The type of the pending safety check.""" message: Optional[str] """Details about the pending safety check.""" class ComputerCallOutput(TypedDict, total=False): """The output of a computer tool call.""" call_id: Required[str] """The ID of the computer tool call that produced the output.""" output: Required[ResponseComputerToolCallOutputScreenshotParam] """A computer screenshot image used with the computer use tool.""" type: Required[Literal["computer_call_output"]] """The type of the computer tool call output. Always `computer_call_output`.""" id: Optional[str] """The ID of the computer tool call output.""" acknowledged_safety_checks: Optional[Iterable[ComputerCallOutputAcknowledgedSafetyCheck]] """ The safety checks reported by the API that have been acknowledged by the developer. """ status: Optional[Literal["in_progress", "completed", "incomplete"]] """The status of the message input. One of `in_progress`, `completed`, or `incomplete`. Populated when input items are returned via API. """ class FunctionCallOutput(TypedDict, total=False): """The output of a function tool call.""" call_id: Required[str] """The unique ID of the function tool call generated by the model.""" output: Required[Union[str, ResponseFunctionCallOutputItemListParam]] """Text, image, or file output of the function tool call.""" type: Required[Literal["function_call_output"]] """The type of the function tool call output. Always `function_call_output`.""" id: Optional[str] """The unique ID of the function tool call output. Populated when this item is returned via API. """ status: Optional[Literal["in_progress", "completed", "incomplete"]] """The status of the item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API. """ class ToolSearchCall(TypedDict, total=False): arguments: Required[object] """The arguments supplied to the tool search call.""" type: Required[Literal["tool_search_call"]] """The item type. Always `tool_search_call`.""" id: Optional[str] """The unique ID of this tool search call.""" call_id: Optional[str] """The unique ID of the tool search call generated by the model.""" execution: Literal["server", "client"] """Whether tool search was executed by the server or by the client.""" status: Optional[Literal["in_progress", "completed", "incomplete"]] """The status of the tool search call.""" class ImageGenerationCall(TypedDict, total=False): """An image generation request made by the model.""" id: Required[str] """The unique ID of the image generation call.""" result: Required[Optional[str]] """The generated image encoded in base64.""" status: Required[Literal["in_progress", "completed", "generating", "failed"]] """The status of the image generation call.""" type: Required[Literal["image_generation_call"]] """The type of the image generation call. Always `image_generation_call`.""" class LocalShellCallAction(TypedDict, total=False): """Execute a shell command on the server.""" command: Required[SequenceNotStr[str]] """The command to run.""" env: Required[Dict[str, str]] """Environment variables to set for the command.""" type: Required[Literal["exec"]] """The type of the local shell action. Always `exec`.""" timeout_ms: Optional[int] """Optional timeout in milliseconds for the command.""" user: Optional[str] """Optional user to run the command as.""" working_directory: Optional[str] """Optional working directory to run the command in.""" class LocalShellCall(TypedDict, total=False): """A tool call to run a command on the local shell.""" id: Required[str] """The unique ID of the local shell call.""" action: Required[LocalShellCallAction] """Execute a shell command on the server.""" call_id: Required[str] """The unique ID of the local shell tool call generated by the model.""" status: Required[Literal["in_progress", "completed", "incomplete"]] """The status of the local shell call.""" type: Required[Literal["local_shell_call"]] """The type of the local shell call. Always `local_shell_call`.""" class LocalShellCallOutput(TypedDict, total=False): """The output of a local shell tool call.""" id: Required[str] """The unique ID of the local shell tool call generated by the model.""" output: Required[str] """A JSON string of the output of the local shell tool call.""" type: Required[Literal["local_shell_call_output"]] """The type of the local shell tool call output. Always `local_shell_call_output`.""" status: Optional[Literal["in_progress", "completed", "incomplete"]] """The status of the item. One of `in_progress`, `completed`, or `incomplete`.""" class ShellCallAction(TypedDict, total=False): """The shell commands and limits that describe how to run the tool call.""" commands: Required[SequenceNotStr[str]] """Ordered shell commands for the execution environment to run.""" max_output_length: Optional[int] """ Maximum number of UTF-8 characters to capture from combined stdout and stderr output. """ timeout_ms: Optional[int] """Maximum wall-clock time in milliseconds to allow the shell commands to run.""" ShellCallEnvironment: TypeAlias = Union[LocalEnvironmentParam, ContainerReferenceParam] class ShellCall(TypedDict, total=False): """A tool representing a request to execute one or more shell commands.""" action: Required[ShellCallAction] """The shell commands and limits that describe how to run the tool call.""" call_id: Required[str] """The unique ID of the shell tool call generated by the model.""" type: Required[Literal["shell_call"]] """The type of the item. Always `shell_call`.""" id: Optional[str] """The unique ID of the shell tool call. Populated when this item is returned via API. """ environment: Optional[ShellCallEnvironment] """The environment to execute the shell commands in.""" status: Optional[Literal["in_progress", "completed", "incomplete"]] """The status of the shell call. One of `in_progress`, `completed`, or `incomplete`. """ class ShellCallOutput(TypedDict, total=False): """The streamed output items emitted by a shell tool call.""" call_id: Required[str] """The unique ID of the shell tool call generated by the model.""" output: Required[Iterable[ResponseFunctionShellCallOutputContentParam]] """ Captured chunks of stdout and stderr output, along with their associated outcomes. """ type: Required[Literal["shell_call_output"]] """The type of the item. Always `shell_call_output`.""" id: Optional[str] """The unique ID of the shell tool call output. Populated when this item is returned via API. """ max_output_length: Optional[int] """ The maximum number of UTF-8 characters captured for this shell call's combined output. """ status: Optional[Literal["in_progress", "completed", "incomplete"]] """The status of the shell call output.""" class ApplyPatchCallOperationCreateFile(TypedDict, total=False): """Instruction for creating a new file via the apply_patch tool.""" diff: Required[str] """Unified diff content to apply when creating the file.""" path: Required[str] """Path of the file to create relative to the workspace root.""" type: Required[Literal["create_file"]] """The operation type. Always `create_file`.""" class ApplyPatchCallOperationDeleteFile(TypedDict, total=False): """Instruction for deleting an existing file via the apply_patch tool.""" path: Required[str] """Path of the file to delete relative to the workspace root.""" type: Required[Literal["delete_file"]] """The operation type. Always `delete_file`.""" class ApplyPatchCallOperationUpdateFile(TypedDict, total=False): """Instruction for updating an existing file via the apply_patch tool.""" diff: Required[str] """Unified diff content to apply to the existing file.""" path: Required[str] """Path of the file to update relative to the workspace root.""" type: Required[Literal["update_file"]] """The operation type. Always `update_file`.""" ApplyPatchCallOperation: TypeAlias = Union[ ApplyPatchCallOperationCreateFile, ApplyPatchCallOperationDeleteFile, ApplyPatchCallOperationUpdateFile ] class ApplyPatchCall(TypedDict, total=False): """ A tool call representing a request to create, delete, or update files using diff patches. """ call_id: Required[str] """The unique ID of the apply patch tool call generated by the model.""" operation: Required[ApplyPatchCallOperation] """ The specific create, delete, or update instruction for the apply_patch tool call. """ status: Required[Literal["in_progress", "completed"]] """The status of the apply patch tool call. One of `in_progress` or `completed`.""" type: Required[Literal["apply_patch_call"]] """The type of the item. Always `apply_patch_call`.""" id: Optional[str] """The unique ID of the apply patch tool call. Populated when this item is returned via API. """ class ApplyPatchCallOutput(TypedDict, total=False): """The streamed output emitted by an apply patch tool call.""" call_id: Required[str] """The unique ID of the apply patch tool call generated by the model.""" status: Required[Literal["completed", "failed"]] """The status of the apply patch tool call output. One of `completed` or `failed`.""" type: Required[Literal["apply_patch_call_output"]] """The type of the item. Always `apply_patch_call_output`.""" id: Optional[str] """The unique ID of the apply patch tool call output. Populated when this item is returned via API. """ output: Optional[str] """ Optional human-readable log text from the apply patch tool (e.g., patch results or errors). """ class McpListToolsTool(TypedDict, total=False): """A tool available on an MCP server.""" input_schema: Required[object] """The JSON schema describing the tool's input.""" name: Required[str] """The name of the tool.""" annotations: Optional[object] """Additional annotations about the tool.""" description: Optional[str] """The description of the tool.""" class McpListTools(TypedDict, total=False): """A list of tools available on an MCP server.""" id: Required[str] """The unique ID of the list.""" server_label: Required[str] """The label of the MCP server.""" tools: Required[Iterable[McpListToolsTool]] """The tools available on the server.""" type: Required[Literal["mcp_list_tools"]] """The type of the item. Always `mcp_list_tools`.""" error: Optional[str] """Error message if the server could not list tools.""" class McpApprovalRequest(TypedDict, total=False): """A request for human approval of a tool invocation.""" id: Required[str] """The unique ID of the approval request.""" arguments: Required[str] """A JSON string of arguments for the tool.""" name: Required[str] """The name of the tool to run.""" server_label: Required[str] """The label of the MCP server making the request.""" type: Required[Literal["mcp_approval_request"]] """The type of the item. Always `mcp_approval_request`.""" class McpApprovalResponse(TypedDict, total=False): """A response to an MCP approval request.""" approval_request_id: Required[str] """The ID of the approval request being answered.""" approve: Required[bool] """Whether the request was approved.""" type: Required[Literal["mcp_approval_response"]] """The type of the item. Always `mcp_approval_response`.""" id: Optional[str] """The unique ID of the approval response""" reason: Optional[str] """Optional reason for the decision.""" class McpCall(TypedDict, total=False): """An invocation of a tool on an MCP server.""" id: Required[str] """The unique ID of the tool call.""" arguments: Required[str] """A JSON string of the arguments passed to the tool.""" name: Required[str] """The name of the tool that was run.""" server_label: Required[str] """The label of the MCP server running the tool.""" type: Required[Literal["mcp_call"]] """The type of the item. Always `mcp_call`.""" approval_request_id: Optional[str] """ Unique identifier for the MCP tool call approval request. Include this value in a subsequent `mcp_approval_response` input to approve or reject the corresponding tool call. """ error: Optional[str] """The error from the tool call, if any.""" output: Optional[str] """The output from the tool call.""" status: Literal["in_progress", "completed", "incomplete", "calling", "failed"] """The status of the tool call. One of `in_progress`, `completed`, `incomplete`, `calling`, or `failed`. """ class ItemReference(TypedDict, total=False): """An internal identifier for an item to reference.""" id: Required[str] """The ID of the item to reference.""" type: Optional[Literal["item_reference"]] """The type of item to reference. Always `item_reference`.""" ResponseInputItemParam: TypeAlias = Union[ EasyInputMessageParam, Message, ResponseOutputMessageParam, ResponseFileSearchToolCallParam, ResponseComputerToolCallParam, ComputerCallOutput, ResponseFunctionWebSearchParam, ResponseFunctionToolCallParam, FunctionCallOutput, ToolSearchCall, ResponseToolSearchOutputItemParamParam, ResponseReasoningItemParam, ResponseCompactionItemParamParam, ImageGenerationCall, ResponseCodeInterpreterToolCallParam, LocalShellCall, LocalShellCallOutput, ShellCall, ShellCallOutput, ApplyPatchCall, ApplyPatchCallOutput, McpListTools, McpApprovalRequest, McpApprovalResponse, McpCall, ResponseCustomToolCallOutputParam, ResponseCustomToolCallParam, ItemReference, ] ================================================ FILE: src/openai/types/responses/response_input_message_content_list.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List from typing_extensions import TypeAlias from .response_input_content import ResponseInputContent __all__ = ["ResponseInputMessageContentList"] ResponseInputMessageContentList: TypeAlias = List[ResponseInputContent] ================================================ FILE: src/openai/types/responses/response_input_message_content_list_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List, Union from typing_extensions import TypeAlias from .response_input_file_param import ResponseInputFileParam from .response_input_text_param import ResponseInputTextParam from .response_input_image_param import ResponseInputImageParam __all__ = ["ResponseInputMessageContentListParam", "ResponseInputContentParam"] ResponseInputContentParam: TypeAlias = Union[ResponseInputTextParam, ResponseInputImageParam, ResponseInputFileParam] ResponseInputMessageContentListParam: TypeAlias = List[ResponseInputContentParam] ================================================ FILE: src/openai/types/responses/response_input_message_item.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel from .response_input_message_content_list import ResponseInputMessageContentList __all__ = ["ResponseInputMessageItem"] class ResponseInputMessageItem(BaseModel): id: str """The unique ID of the message input.""" content: ResponseInputMessageContentList """ A list of one or many input items to the model, containing different content types. """ role: Literal["user", "system", "developer"] """The role of the message input. One of `user`, `system`, or `developer`.""" status: Optional[Literal["in_progress", "completed", "incomplete"]] = None """The status of item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API. """ type: Optional[Literal["message"]] = None """The type of the message input. Always set to `message`.""" ================================================ FILE: src/openai/types/responses/response_input_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, List, Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import SequenceNotStr from .local_environment_param import LocalEnvironmentParam from .easy_input_message_param import EasyInputMessageParam from .container_reference_param import ContainerReferenceParam from .response_output_message_param import ResponseOutputMessageParam from .response_reasoning_item_param import ResponseReasoningItemParam from .response_custom_tool_call_param import ResponseCustomToolCallParam from .response_computer_tool_call_param import ResponseComputerToolCallParam from .response_function_tool_call_param import ResponseFunctionToolCallParam from .response_function_web_search_param import ResponseFunctionWebSearchParam from .response_compaction_item_param_param import ResponseCompactionItemParamParam from .response_file_search_tool_call_param import ResponseFileSearchToolCallParam from .response_custom_tool_call_output_param import ResponseCustomToolCallOutputParam from .response_code_interpreter_tool_call_param import ResponseCodeInterpreterToolCallParam from .response_input_message_content_list_param import ResponseInputMessageContentListParam from .response_tool_search_output_item_param_param import ResponseToolSearchOutputItemParamParam from .response_function_call_output_item_list_param import ResponseFunctionCallOutputItemListParam from .response_function_shell_call_output_content_param import ResponseFunctionShellCallOutputContentParam from .response_computer_tool_call_output_screenshot_param import ResponseComputerToolCallOutputScreenshotParam __all__ = [ "ResponseInputParam", "ResponseInputItemParam", "Message", "ComputerCallOutput", "ComputerCallOutputAcknowledgedSafetyCheck", "FunctionCallOutput", "ToolSearchCall", "ImageGenerationCall", "LocalShellCall", "LocalShellCallAction", "LocalShellCallOutput", "ShellCall", "ShellCallAction", "ShellCallEnvironment", "ShellCallOutput", "ApplyPatchCall", "ApplyPatchCallOperation", "ApplyPatchCallOperationCreateFile", "ApplyPatchCallOperationDeleteFile", "ApplyPatchCallOperationUpdateFile", "ApplyPatchCallOutput", "McpListTools", "McpListToolsTool", "McpApprovalRequest", "McpApprovalResponse", "McpCall", "ItemReference", ] class Message(TypedDict, total=False): """ A message input to the model with a role indicating instruction following hierarchy. Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role. """ content: Required[ResponseInputMessageContentListParam] """ A list of one or many input items to the model, containing different content types. """ role: Required[Literal["user", "system", "developer"]] """The role of the message input. One of `user`, `system`, or `developer`.""" status: Literal["in_progress", "completed", "incomplete"] """The status of item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API. """ type: Literal["message"] """The type of the message input. Always set to `message`.""" class ComputerCallOutputAcknowledgedSafetyCheck(TypedDict, total=False): """A pending safety check for the computer call.""" id: Required[str] """The ID of the pending safety check.""" code: Optional[str] """The type of the pending safety check.""" message: Optional[str] """Details about the pending safety check.""" class ComputerCallOutput(TypedDict, total=False): """The output of a computer tool call.""" call_id: Required[str] """The ID of the computer tool call that produced the output.""" output: Required[ResponseComputerToolCallOutputScreenshotParam] """A computer screenshot image used with the computer use tool.""" type: Required[Literal["computer_call_output"]] """The type of the computer tool call output. Always `computer_call_output`.""" id: Optional[str] """The ID of the computer tool call output.""" acknowledged_safety_checks: Optional[Iterable[ComputerCallOutputAcknowledgedSafetyCheck]] """ The safety checks reported by the API that have been acknowledged by the developer. """ status: Optional[Literal["in_progress", "completed", "incomplete"]] """The status of the message input. One of `in_progress`, `completed`, or `incomplete`. Populated when input items are returned via API. """ class FunctionCallOutput(TypedDict, total=False): """The output of a function tool call.""" call_id: Required[str] """The unique ID of the function tool call generated by the model.""" output: Required[Union[str, ResponseFunctionCallOutputItemListParam]] """Text, image, or file output of the function tool call.""" type: Required[Literal["function_call_output"]] """The type of the function tool call output. Always `function_call_output`.""" id: Optional[str] """The unique ID of the function tool call output. Populated when this item is returned via API. """ status: Optional[Literal["in_progress", "completed", "incomplete"]] """The status of the item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API. """ class ToolSearchCall(TypedDict, total=False): arguments: Required[object] """The arguments supplied to the tool search call.""" type: Required[Literal["tool_search_call"]] """The item type. Always `tool_search_call`.""" id: Optional[str] """The unique ID of this tool search call.""" call_id: Optional[str] """The unique ID of the tool search call generated by the model.""" execution: Literal["server", "client"] """Whether tool search was executed by the server or by the client.""" status: Optional[Literal["in_progress", "completed", "incomplete"]] """The status of the tool search call.""" class ImageGenerationCall(TypedDict, total=False): """An image generation request made by the model.""" id: Required[str] """The unique ID of the image generation call.""" result: Required[Optional[str]] """The generated image encoded in base64.""" status: Required[Literal["in_progress", "completed", "generating", "failed"]] """The status of the image generation call.""" type: Required[Literal["image_generation_call"]] """The type of the image generation call. Always `image_generation_call`.""" class LocalShellCallAction(TypedDict, total=False): """Execute a shell command on the server.""" command: Required[SequenceNotStr[str]] """The command to run.""" env: Required[Dict[str, str]] """Environment variables to set for the command.""" type: Required[Literal["exec"]] """The type of the local shell action. Always `exec`.""" timeout_ms: Optional[int] """Optional timeout in milliseconds for the command.""" user: Optional[str] """Optional user to run the command as.""" working_directory: Optional[str] """Optional working directory to run the command in.""" class LocalShellCall(TypedDict, total=False): """A tool call to run a command on the local shell.""" id: Required[str] """The unique ID of the local shell call.""" action: Required[LocalShellCallAction] """Execute a shell command on the server.""" call_id: Required[str] """The unique ID of the local shell tool call generated by the model.""" status: Required[Literal["in_progress", "completed", "incomplete"]] """The status of the local shell call.""" type: Required[Literal["local_shell_call"]] """The type of the local shell call. Always `local_shell_call`.""" class LocalShellCallOutput(TypedDict, total=False): """The output of a local shell tool call.""" id: Required[str] """The unique ID of the local shell tool call generated by the model.""" output: Required[str] """A JSON string of the output of the local shell tool call.""" type: Required[Literal["local_shell_call_output"]] """The type of the local shell tool call output. Always `local_shell_call_output`.""" status: Optional[Literal["in_progress", "completed", "incomplete"]] """The status of the item. One of `in_progress`, `completed`, or `incomplete`.""" class ShellCallAction(TypedDict, total=False): """The shell commands and limits that describe how to run the tool call.""" commands: Required[SequenceNotStr[str]] """Ordered shell commands for the execution environment to run.""" max_output_length: Optional[int] """ Maximum number of UTF-8 characters to capture from combined stdout and stderr output. """ timeout_ms: Optional[int] """Maximum wall-clock time in milliseconds to allow the shell commands to run.""" ShellCallEnvironment: TypeAlias = Union[LocalEnvironmentParam, ContainerReferenceParam] class ShellCall(TypedDict, total=False): """A tool representing a request to execute one or more shell commands.""" action: Required[ShellCallAction] """The shell commands and limits that describe how to run the tool call.""" call_id: Required[str] """The unique ID of the shell tool call generated by the model.""" type: Required[Literal["shell_call"]] """The type of the item. Always `shell_call`.""" id: Optional[str] """The unique ID of the shell tool call. Populated when this item is returned via API. """ environment: Optional[ShellCallEnvironment] """The environment to execute the shell commands in.""" status: Optional[Literal["in_progress", "completed", "incomplete"]] """The status of the shell call. One of `in_progress`, `completed`, or `incomplete`. """ class ShellCallOutput(TypedDict, total=False): """The streamed output items emitted by a shell tool call.""" call_id: Required[str] """The unique ID of the shell tool call generated by the model.""" output: Required[Iterable[ResponseFunctionShellCallOutputContentParam]] """ Captured chunks of stdout and stderr output, along with their associated outcomes. """ type: Required[Literal["shell_call_output"]] """The type of the item. Always `shell_call_output`.""" id: Optional[str] """The unique ID of the shell tool call output. Populated when this item is returned via API. """ max_output_length: Optional[int] """ The maximum number of UTF-8 characters captured for this shell call's combined output. """ status: Optional[Literal["in_progress", "completed", "incomplete"]] """The status of the shell call output.""" class ApplyPatchCallOperationCreateFile(TypedDict, total=False): """Instruction for creating a new file via the apply_patch tool.""" diff: Required[str] """Unified diff content to apply when creating the file.""" path: Required[str] """Path of the file to create relative to the workspace root.""" type: Required[Literal["create_file"]] """The operation type. Always `create_file`.""" class ApplyPatchCallOperationDeleteFile(TypedDict, total=False): """Instruction for deleting an existing file via the apply_patch tool.""" path: Required[str] """Path of the file to delete relative to the workspace root.""" type: Required[Literal["delete_file"]] """The operation type. Always `delete_file`.""" class ApplyPatchCallOperationUpdateFile(TypedDict, total=False): """Instruction for updating an existing file via the apply_patch tool.""" diff: Required[str] """Unified diff content to apply to the existing file.""" path: Required[str] """Path of the file to update relative to the workspace root.""" type: Required[Literal["update_file"]] """The operation type. Always `update_file`.""" ApplyPatchCallOperation: TypeAlias = Union[ ApplyPatchCallOperationCreateFile, ApplyPatchCallOperationDeleteFile, ApplyPatchCallOperationUpdateFile ] class ApplyPatchCall(TypedDict, total=False): """ A tool call representing a request to create, delete, or update files using diff patches. """ call_id: Required[str] """The unique ID of the apply patch tool call generated by the model.""" operation: Required[ApplyPatchCallOperation] """ The specific create, delete, or update instruction for the apply_patch tool call. """ status: Required[Literal["in_progress", "completed"]] """The status of the apply patch tool call. One of `in_progress` or `completed`.""" type: Required[Literal["apply_patch_call"]] """The type of the item. Always `apply_patch_call`.""" id: Optional[str] """The unique ID of the apply patch tool call. Populated when this item is returned via API. """ class ApplyPatchCallOutput(TypedDict, total=False): """The streamed output emitted by an apply patch tool call.""" call_id: Required[str] """The unique ID of the apply patch tool call generated by the model.""" status: Required[Literal["completed", "failed"]] """The status of the apply patch tool call output. One of `completed` or `failed`.""" type: Required[Literal["apply_patch_call_output"]] """The type of the item. Always `apply_patch_call_output`.""" id: Optional[str] """The unique ID of the apply patch tool call output. Populated when this item is returned via API. """ output: Optional[str] """ Optional human-readable log text from the apply patch tool (e.g., patch results or errors). """ class McpListToolsTool(TypedDict, total=False): """A tool available on an MCP server.""" input_schema: Required[object] """The JSON schema describing the tool's input.""" name: Required[str] """The name of the tool.""" annotations: Optional[object] """Additional annotations about the tool.""" description: Optional[str] """The description of the tool.""" class McpListTools(TypedDict, total=False): """A list of tools available on an MCP server.""" id: Required[str] """The unique ID of the list.""" server_label: Required[str] """The label of the MCP server.""" tools: Required[Iterable[McpListToolsTool]] """The tools available on the server.""" type: Required[Literal["mcp_list_tools"]] """The type of the item. Always `mcp_list_tools`.""" error: Optional[str] """Error message if the server could not list tools.""" class McpApprovalRequest(TypedDict, total=False): """A request for human approval of a tool invocation.""" id: Required[str] """The unique ID of the approval request.""" arguments: Required[str] """A JSON string of arguments for the tool.""" name: Required[str] """The name of the tool to run.""" server_label: Required[str] """The label of the MCP server making the request.""" type: Required[Literal["mcp_approval_request"]] """The type of the item. Always `mcp_approval_request`.""" class McpApprovalResponse(TypedDict, total=False): """A response to an MCP approval request.""" approval_request_id: Required[str] """The ID of the approval request being answered.""" approve: Required[bool] """Whether the request was approved.""" type: Required[Literal["mcp_approval_response"]] """The type of the item. Always `mcp_approval_response`.""" id: Optional[str] """The unique ID of the approval response""" reason: Optional[str] """Optional reason for the decision.""" class McpCall(TypedDict, total=False): """An invocation of a tool on an MCP server.""" id: Required[str] """The unique ID of the tool call.""" arguments: Required[str] """A JSON string of the arguments passed to the tool.""" name: Required[str] """The name of the tool that was run.""" server_label: Required[str] """The label of the MCP server running the tool.""" type: Required[Literal["mcp_call"]] """The type of the item. Always `mcp_call`.""" approval_request_id: Optional[str] """ Unique identifier for the MCP tool call approval request. Include this value in a subsequent `mcp_approval_response` input to approve or reject the corresponding tool call. """ error: Optional[str] """The error from the tool call, if any.""" output: Optional[str] """The output from the tool call.""" status: Literal["in_progress", "completed", "incomplete", "calling", "failed"] """The status of the tool call. One of `in_progress`, `completed`, `incomplete`, `calling`, or `failed`. """ class ItemReference(TypedDict, total=False): """An internal identifier for an item to reference.""" id: Required[str] """The ID of the item to reference.""" type: Optional[Literal["item_reference"]] """The type of item to reference. Always `item_reference`.""" ResponseInputItemParam: TypeAlias = Union[ EasyInputMessageParam, Message, ResponseOutputMessageParam, ResponseFileSearchToolCallParam, ResponseComputerToolCallParam, ComputerCallOutput, ResponseFunctionWebSearchParam, ResponseFunctionToolCallParam, FunctionCallOutput, ToolSearchCall, ResponseToolSearchOutputItemParamParam, ResponseReasoningItemParam, ResponseCompactionItemParamParam, ImageGenerationCall, ResponseCodeInterpreterToolCallParam, LocalShellCall, LocalShellCallOutput, ShellCall, ShellCallOutput, ApplyPatchCall, ApplyPatchCallOutput, McpListTools, McpApprovalRequest, McpApprovalResponse, McpCall, ResponseCustomToolCallOutputParam, ResponseCustomToolCallParam, ItemReference, ] ResponseInputParam: TypeAlias = List[ResponseInputItemParam] ================================================ FILE: src/openai/types/responses/response_input_text.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseInputText"] class ResponseInputText(BaseModel): """A text input to the model.""" text: str """The text input to the model.""" type: Literal["input_text"] """The type of the input item. Always `input_text`.""" ================================================ FILE: src/openai/types/responses/response_input_text_content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseInputTextContent"] class ResponseInputTextContent(BaseModel): """A text input to the model.""" text: str """The text input to the model.""" type: Literal["input_text"] """The type of the input item. Always `input_text`.""" ================================================ FILE: src/openai/types/responses/response_input_text_content_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ResponseInputTextContentParam"] class ResponseInputTextContentParam(TypedDict, total=False): """A text input to the model.""" text: Required[str] """The text input to the model.""" type: Required[Literal["input_text"]] """The type of the input item. Always `input_text`.""" ================================================ FILE: src/openai/types/responses/response_input_text_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ResponseInputTextParam"] class ResponseInputTextParam(TypedDict, total=False): """A text input to the model.""" text: Required[str] """The text input to the model.""" type: Required[Literal["input_text"]] """The type of the input item. Always `input_text`.""" ================================================ FILE: src/openai/types/responses/response_item.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .response_output_message import ResponseOutputMessage from .response_tool_search_call import ResponseToolSearchCall from .response_computer_tool_call import ResponseComputerToolCall from .response_input_message_item import ResponseInputMessageItem from .response_function_web_search import ResponseFunctionWebSearch from .response_apply_patch_tool_call import ResponseApplyPatchToolCall from .response_file_search_tool_call import ResponseFileSearchToolCall from .response_function_tool_call_item import ResponseFunctionToolCallItem from .response_tool_search_output_item import ResponseToolSearchOutputItem from .response_function_shell_tool_call import ResponseFunctionShellToolCall from .response_code_interpreter_tool_call import ResponseCodeInterpreterToolCall from .response_apply_patch_tool_call_output import ResponseApplyPatchToolCallOutput from .response_computer_tool_call_output_item import ResponseComputerToolCallOutputItem from .response_function_tool_call_output_item import ResponseFunctionToolCallOutputItem from .response_function_shell_tool_call_output import ResponseFunctionShellToolCallOutput __all__ = [ "ResponseItem", "ImageGenerationCall", "LocalShellCall", "LocalShellCallAction", "LocalShellCallOutput", "McpListTools", "McpListToolsTool", "McpApprovalRequest", "McpApprovalResponse", "McpCall", ] class ImageGenerationCall(BaseModel): """An image generation request made by the model.""" id: str """The unique ID of the image generation call.""" result: Optional[str] = None """The generated image encoded in base64.""" status: Literal["in_progress", "completed", "generating", "failed"] """The status of the image generation call.""" type: Literal["image_generation_call"] """The type of the image generation call. Always `image_generation_call`.""" class LocalShellCallAction(BaseModel): """Execute a shell command on the server.""" command: List[str] """The command to run.""" env: Dict[str, str] """Environment variables to set for the command.""" type: Literal["exec"] """The type of the local shell action. Always `exec`.""" timeout_ms: Optional[int] = None """Optional timeout in milliseconds for the command.""" user: Optional[str] = None """Optional user to run the command as.""" working_directory: Optional[str] = None """Optional working directory to run the command in.""" class LocalShellCall(BaseModel): """A tool call to run a command on the local shell.""" id: str """The unique ID of the local shell call.""" action: LocalShellCallAction """Execute a shell command on the server.""" call_id: str """The unique ID of the local shell tool call generated by the model.""" status: Literal["in_progress", "completed", "incomplete"] """The status of the local shell call.""" type: Literal["local_shell_call"] """The type of the local shell call. Always `local_shell_call`.""" class LocalShellCallOutput(BaseModel): """The output of a local shell tool call.""" id: str """The unique ID of the local shell tool call generated by the model.""" output: str """A JSON string of the output of the local shell tool call.""" type: Literal["local_shell_call_output"] """The type of the local shell tool call output. Always `local_shell_call_output`.""" status: Optional[Literal["in_progress", "completed", "incomplete"]] = None """The status of the item. One of `in_progress`, `completed`, or `incomplete`.""" class McpListToolsTool(BaseModel): """A tool available on an MCP server.""" input_schema: object """The JSON schema describing the tool's input.""" name: str """The name of the tool.""" annotations: Optional[object] = None """Additional annotations about the tool.""" description: Optional[str] = None """The description of the tool.""" class McpListTools(BaseModel): """A list of tools available on an MCP server.""" id: str """The unique ID of the list.""" server_label: str """The label of the MCP server.""" tools: List[McpListToolsTool] """The tools available on the server.""" type: Literal["mcp_list_tools"] """The type of the item. Always `mcp_list_tools`.""" error: Optional[str] = None """Error message if the server could not list tools.""" class McpApprovalRequest(BaseModel): """A request for human approval of a tool invocation.""" id: str """The unique ID of the approval request.""" arguments: str """A JSON string of arguments for the tool.""" name: str """The name of the tool to run.""" server_label: str """The label of the MCP server making the request.""" type: Literal["mcp_approval_request"] """The type of the item. Always `mcp_approval_request`.""" class McpApprovalResponse(BaseModel): """A response to an MCP approval request.""" id: str """The unique ID of the approval response""" approval_request_id: str """The ID of the approval request being answered.""" approve: bool """Whether the request was approved.""" type: Literal["mcp_approval_response"] """The type of the item. Always `mcp_approval_response`.""" reason: Optional[str] = None """Optional reason for the decision.""" class McpCall(BaseModel): """An invocation of a tool on an MCP server.""" id: str """The unique ID of the tool call.""" arguments: str """A JSON string of the arguments passed to the tool.""" name: str """The name of the tool that was run.""" server_label: str """The label of the MCP server running the tool.""" type: Literal["mcp_call"] """The type of the item. Always `mcp_call`.""" approval_request_id: Optional[str] = None """ Unique identifier for the MCP tool call approval request. Include this value in a subsequent `mcp_approval_response` input to approve or reject the corresponding tool call. """ error: Optional[str] = None """The error from the tool call, if any.""" output: Optional[str] = None """The output from the tool call.""" status: Optional[Literal["in_progress", "completed", "incomplete", "calling", "failed"]] = None """The status of the tool call. One of `in_progress`, `completed`, `incomplete`, `calling`, or `failed`. """ ResponseItem: TypeAlias = Annotated[ Union[ ResponseInputMessageItem, ResponseOutputMessage, ResponseFileSearchToolCall, ResponseComputerToolCall, ResponseComputerToolCallOutputItem, ResponseFunctionWebSearch, ResponseFunctionToolCallItem, ResponseFunctionToolCallOutputItem, ResponseToolSearchCall, ResponseToolSearchOutputItem, ImageGenerationCall, ResponseCodeInterpreterToolCall, LocalShellCall, LocalShellCallOutput, ResponseFunctionShellToolCall, ResponseFunctionShellToolCallOutput, ResponseApplyPatchToolCall, ResponseApplyPatchToolCallOutput, McpListTools, McpApprovalRequest, McpApprovalResponse, McpCall, ], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/types/responses/response_item_list.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List from typing_extensions import Literal from ..._models import BaseModel from .response_item import ResponseItem __all__ = ["ResponseItemList"] class ResponseItemList(BaseModel): """A list of Response items.""" data: List[ResponseItem] """A list of items used to generate this response.""" first_id: str """The ID of the first item in the list.""" has_more: bool """Whether there are more items available.""" last_id: str """The ID of the last item in the list.""" object: Literal["list"] """The type of object returned, must be `list`.""" ================================================ FILE: src/openai/types/responses/response_local_environment.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseLocalEnvironment"] class ResponseLocalEnvironment(BaseModel): """Represents the use of a local environment to perform shell actions.""" type: Literal["local"] """The environment type. Always `local`.""" ================================================ FILE: src/openai/types/responses/response_mcp_call_arguments_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseMcpCallArgumentsDeltaEvent"] class ResponseMcpCallArgumentsDeltaEvent(BaseModel): """ Emitted when there is a delta (partial update) to the arguments of an MCP tool call. """ delta: str """ A JSON string containing the partial update to the arguments for the MCP tool call. """ item_id: str """The unique identifier of the MCP tool call item being processed.""" output_index: int """The index of the output item in the response's output array.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.mcp_call_arguments.delta"] """The type of the event. Always 'response.mcp_call_arguments.delta'.""" ================================================ FILE: src/openai/types/responses/response_mcp_call_arguments_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseMcpCallArgumentsDoneEvent"] class ResponseMcpCallArgumentsDoneEvent(BaseModel): """Emitted when the arguments for an MCP tool call are finalized.""" arguments: str """A JSON string containing the finalized arguments for the MCP tool call.""" item_id: str """The unique identifier of the MCP tool call item being processed.""" output_index: int """The index of the output item in the response's output array.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.mcp_call_arguments.done"] """The type of the event. Always 'response.mcp_call_arguments.done'.""" ================================================ FILE: src/openai/types/responses/response_mcp_call_completed_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseMcpCallCompletedEvent"] class ResponseMcpCallCompletedEvent(BaseModel): """Emitted when an MCP tool call has completed successfully.""" item_id: str """The ID of the MCP tool call item that completed.""" output_index: int """The index of the output item that completed.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.mcp_call.completed"] """The type of the event. Always 'response.mcp_call.completed'.""" ================================================ FILE: src/openai/types/responses/response_mcp_call_failed_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseMcpCallFailedEvent"] class ResponseMcpCallFailedEvent(BaseModel): """Emitted when an MCP tool call has failed.""" item_id: str """The ID of the MCP tool call item that failed.""" output_index: int """The index of the output item that failed.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.mcp_call.failed"] """The type of the event. Always 'response.mcp_call.failed'.""" ================================================ FILE: src/openai/types/responses/response_mcp_call_in_progress_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseMcpCallInProgressEvent"] class ResponseMcpCallInProgressEvent(BaseModel): """Emitted when an MCP tool call is in progress.""" item_id: str """The unique identifier of the MCP tool call item being processed.""" output_index: int """The index of the output item in the response's output array.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.mcp_call.in_progress"] """The type of the event. Always 'response.mcp_call.in_progress'.""" ================================================ FILE: src/openai/types/responses/response_mcp_list_tools_completed_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseMcpListToolsCompletedEvent"] class ResponseMcpListToolsCompletedEvent(BaseModel): """Emitted when the list of available MCP tools has been successfully retrieved.""" item_id: str """The ID of the MCP tool call item that produced this output.""" output_index: int """The index of the output item that was processed.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.mcp_list_tools.completed"] """The type of the event. Always 'response.mcp_list_tools.completed'.""" ================================================ FILE: src/openai/types/responses/response_mcp_list_tools_failed_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseMcpListToolsFailedEvent"] class ResponseMcpListToolsFailedEvent(BaseModel): """Emitted when the attempt to list available MCP tools has failed.""" item_id: str """The ID of the MCP tool call item that failed.""" output_index: int """The index of the output item that failed.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.mcp_list_tools.failed"] """The type of the event. Always 'response.mcp_list_tools.failed'.""" ================================================ FILE: src/openai/types/responses/response_mcp_list_tools_in_progress_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseMcpListToolsInProgressEvent"] class ResponseMcpListToolsInProgressEvent(BaseModel): """ Emitted when the system is in the process of retrieving the list of available MCP tools. """ item_id: str """The ID of the MCP tool call item that is being processed.""" output_index: int """The index of the output item that is being processed.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.mcp_list_tools.in_progress"] """The type of the event. Always 'response.mcp_list_tools.in_progress'.""" ================================================ FILE: src/openai/types/responses/response_output_item.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .response_output_message import ResponseOutputMessage from .response_reasoning_item import ResponseReasoningItem from .response_compaction_item import ResponseCompactionItem from .response_custom_tool_call import ResponseCustomToolCall from .response_tool_search_call import ResponseToolSearchCall from .response_computer_tool_call import ResponseComputerToolCall from .response_function_tool_call import ResponseFunctionToolCall from .response_function_web_search import ResponseFunctionWebSearch from .response_apply_patch_tool_call import ResponseApplyPatchToolCall from .response_file_search_tool_call import ResponseFileSearchToolCall from .response_tool_search_output_item import ResponseToolSearchOutputItem from .response_function_shell_tool_call import ResponseFunctionShellToolCall from .response_code_interpreter_tool_call import ResponseCodeInterpreterToolCall from .response_apply_patch_tool_call_output import ResponseApplyPatchToolCallOutput from .response_function_shell_tool_call_output import ResponseFunctionShellToolCallOutput __all__ = [ "ResponseOutputItem", "ImageGenerationCall", "LocalShellCall", "LocalShellCallAction", "McpCall", "McpListTools", "McpListToolsTool", "McpApprovalRequest", ] class ImageGenerationCall(BaseModel): """An image generation request made by the model.""" id: str """The unique ID of the image generation call.""" result: Optional[str] = None """The generated image encoded in base64.""" status: Literal["in_progress", "completed", "generating", "failed"] """The status of the image generation call.""" type: Literal["image_generation_call"] """The type of the image generation call. Always `image_generation_call`.""" class LocalShellCallAction(BaseModel): """Execute a shell command on the server.""" command: List[str] """The command to run.""" env: Dict[str, str] """Environment variables to set for the command.""" type: Literal["exec"] """The type of the local shell action. Always `exec`.""" timeout_ms: Optional[int] = None """Optional timeout in milliseconds for the command.""" user: Optional[str] = None """Optional user to run the command as.""" working_directory: Optional[str] = None """Optional working directory to run the command in.""" class LocalShellCall(BaseModel): """A tool call to run a command on the local shell.""" id: str """The unique ID of the local shell call.""" action: LocalShellCallAction """Execute a shell command on the server.""" call_id: str """The unique ID of the local shell tool call generated by the model.""" status: Literal["in_progress", "completed", "incomplete"] """The status of the local shell call.""" type: Literal["local_shell_call"] """The type of the local shell call. Always `local_shell_call`.""" class McpCall(BaseModel): """An invocation of a tool on an MCP server.""" id: str """The unique ID of the tool call.""" arguments: str """A JSON string of the arguments passed to the tool.""" name: str """The name of the tool that was run.""" server_label: str """The label of the MCP server running the tool.""" type: Literal["mcp_call"] """The type of the item. Always `mcp_call`.""" approval_request_id: Optional[str] = None """ Unique identifier for the MCP tool call approval request. Include this value in a subsequent `mcp_approval_response` input to approve or reject the corresponding tool call. """ error: Optional[str] = None """The error from the tool call, if any.""" output: Optional[str] = None """The output from the tool call.""" status: Optional[Literal["in_progress", "completed", "incomplete", "calling", "failed"]] = None """The status of the tool call. One of `in_progress`, `completed`, `incomplete`, `calling`, or `failed`. """ class McpListToolsTool(BaseModel): """A tool available on an MCP server.""" input_schema: object """The JSON schema describing the tool's input.""" name: str """The name of the tool.""" annotations: Optional[object] = None """Additional annotations about the tool.""" description: Optional[str] = None """The description of the tool.""" class McpListTools(BaseModel): """A list of tools available on an MCP server.""" id: str """The unique ID of the list.""" server_label: str """The label of the MCP server.""" tools: List[McpListToolsTool] """The tools available on the server.""" type: Literal["mcp_list_tools"] """The type of the item. Always `mcp_list_tools`.""" error: Optional[str] = None """Error message if the server could not list tools.""" class McpApprovalRequest(BaseModel): """A request for human approval of a tool invocation.""" id: str """The unique ID of the approval request.""" arguments: str """A JSON string of arguments for the tool.""" name: str """The name of the tool to run.""" server_label: str """The label of the MCP server making the request.""" type: Literal["mcp_approval_request"] """The type of the item. Always `mcp_approval_request`.""" ResponseOutputItem: TypeAlias = Annotated[ Union[ ResponseOutputMessage, ResponseFileSearchToolCall, ResponseFunctionToolCall, ResponseFunctionWebSearch, ResponseComputerToolCall, ResponseReasoningItem, ResponseToolSearchCall, ResponseToolSearchOutputItem, ResponseCompactionItem, ImageGenerationCall, ResponseCodeInterpreterToolCall, LocalShellCall, ResponseFunctionShellToolCall, ResponseFunctionShellToolCallOutput, ResponseApplyPatchToolCall, ResponseApplyPatchToolCallOutput, McpCall, McpListTools, McpApprovalRequest, ResponseCustomToolCall, ], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/types/responses/response_output_item_added_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel from .response_output_item import ResponseOutputItem __all__ = ["ResponseOutputItemAddedEvent"] class ResponseOutputItemAddedEvent(BaseModel): """Emitted when a new output item is added.""" item: ResponseOutputItem """The output item that was added.""" output_index: int """The index of the output item that was added.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.output_item.added"] """The type of the event. Always `response.output_item.added`.""" ================================================ FILE: src/openai/types/responses/response_output_item_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel from .response_output_item import ResponseOutputItem __all__ = ["ResponseOutputItemDoneEvent"] class ResponseOutputItemDoneEvent(BaseModel): """Emitted when an output item is marked done.""" item: ResponseOutputItem """The output item that was marked done.""" output_index: int """The index of the output item that was marked done.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.output_item.done"] """The type of the event. Always `response.output_item.done`.""" ================================================ FILE: src/openai/types/responses/response_output_message.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel from .response_output_text import ResponseOutputText from .response_output_refusal import ResponseOutputRefusal __all__ = ["ResponseOutputMessage", "Content"] Content: TypeAlias = Annotated[Union[ResponseOutputText, ResponseOutputRefusal], PropertyInfo(discriminator="type")] class ResponseOutputMessage(BaseModel): """An output message from the model.""" id: str """The unique ID of the output message.""" content: List[Content] """The content of the output message.""" role: Literal["assistant"] """The role of the output message. Always `assistant`.""" status: Literal["in_progress", "completed", "incomplete"] """The status of the message input. One of `in_progress`, `completed`, or `incomplete`. Populated when input items are returned via API. """ type: Literal["message"] """The type of the output message. Always `message`.""" phase: Optional[Literal["commentary", "final_answer"]] = None """ Labels an `assistant` message as intermediate commentary (`commentary`) or the final answer (`final_answer`). For models like `gpt-5.3-codex` and beyond, when sending follow-up requests, preserve and resend phase on all assistant messages — dropping it can degrade performance. Not used for user messages. """ ================================================ FILE: src/openai/types/responses/response_output_message_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from .response_output_text_param import ResponseOutputTextParam from .response_output_refusal_param import ResponseOutputRefusalParam __all__ = ["ResponseOutputMessageParam", "Content"] Content: TypeAlias = Union[ResponseOutputTextParam, ResponseOutputRefusalParam] class ResponseOutputMessageParam(TypedDict, total=False): """An output message from the model.""" id: Required[str] """The unique ID of the output message.""" content: Required[Iterable[Content]] """The content of the output message.""" role: Required[Literal["assistant"]] """The role of the output message. Always `assistant`.""" status: Required[Literal["in_progress", "completed", "incomplete"]] """The status of the message input. One of `in_progress`, `completed`, or `incomplete`. Populated when input items are returned via API. """ type: Required[Literal["message"]] """The type of the output message. Always `message`.""" phase: Optional[Literal["commentary", "final_answer"]] """ Labels an `assistant` message as intermediate commentary (`commentary`) or the final answer (`final_answer`). For models like `gpt-5.3-codex` and beyond, when sending follow-up requests, preserve and resend phase on all assistant messages — dropping it can degrade performance. Not used for user messages. """ ================================================ FILE: src/openai/types/responses/response_output_refusal.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseOutputRefusal"] class ResponseOutputRefusal(BaseModel): """A refusal from the model.""" refusal: str """The refusal explanation from the model.""" type: Literal["refusal"] """The type of the refusal. Always `refusal`.""" ================================================ FILE: src/openai/types/responses/response_output_refusal_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ResponseOutputRefusalParam"] class ResponseOutputRefusalParam(TypedDict, total=False): """A refusal from the model.""" refusal: Required[str] """The refusal explanation from the model.""" type: Required[Literal["refusal"]] """The type of the refusal. Always `refusal`.""" ================================================ FILE: src/openai/types/responses/response_output_text.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = [ "ResponseOutputText", "Annotation", "AnnotationFileCitation", "AnnotationURLCitation", "AnnotationContainerFileCitation", "AnnotationFilePath", "Logprob", "LogprobTopLogprob", ] class AnnotationFileCitation(BaseModel): """A citation to a file.""" file_id: str """The ID of the file.""" filename: str """The filename of the file cited.""" index: int """The index of the file in the list of files.""" type: Literal["file_citation"] """The type of the file citation. Always `file_citation`.""" class AnnotationURLCitation(BaseModel): """A citation for a web resource used to generate a model response.""" end_index: int """The index of the last character of the URL citation in the message.""" start_index: int """The index of the first character of the URL citation in the message.""" title: str """The title of the web resource.""" type: Literal["url_citation"] """The type of the URL citation. Always `url_citation`.""" url: str """The URL of the web resource.""" class AnnotationContainerFileCitation(BaseModel): """A citation for a container file used to generate a model response.""" container_id: str """The ID of the container file.""" end_index: int """The index of the last character of the container file citation in the message.""" file_id: str """The ID of the file.""" filename: str """The filename of the container file cited.""" start_index: int """The index of the first character of the container file citation in the message.""" type: Literal["container_file_citation"] """The type of the container file citation. Always `container_file_citation`.""" class AnnotationFilePath(BaseModel): """A path to a file.""" file_id: str """The ID of the file.""" index: int """The index of the file in the list of files.""" type: Literal["file_path"] """The type of the file path. Always `file_path`.""" Annotation: TypeAlias = Annotated[ Union[AnnotationFileCitation, AnnotationURLCitation, AnnotationContainerFileCitation, AnnotationFilePath], PropertyInfo(discriminator="type"), ] class LogprobTopLogprob(BaseModel): """The top log probability of a token.""" token: str bytes: List[int] logprob: float class Logprob(BaseModel): """The log probability of a token.""" token: str bytes: List[int] logprob: float top_logprobs: List[LogprobTopLogprob] class ResponseOutputText(BaseModel): """A text output from the model.""" annotations: List[Annotation] """The annotations of the text output.""" text: str """The text output from the model.""" type: Literal["output_text"] """The type of the output text. Always `output_text`.""" logprobs: Optional[List[Logprob]] = None ================================================ FILE: src/openai/types/responses/response_output_text_annotation_added_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseOutputTextAnnotationAddedEvent"] class ResponseOutputTextAnnotationAddedEvent(BaseModel): """Emitted when an annotation is added to output text content.""" annotation: object """The annotation object being added. (See annotation schema for details.)""" annotation_index: int """The index of the annotation within the content part.""" content_index: int """The index of the content part within the output item.""" item_id: str """The unique identifier of the item to which the annotation is being added.""" output_index: int """The index of the output item in the response's output array.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.output_text.annotation.added"] """The type of the event. Always 'response.output_text.annotation.added'.""" ================================================ FILE: src/openai/types/responses/response_output_text_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable from typing_extensions import Literal, Required, TypeAlias, TypedDict __all__ = [ "ResponseOutputTextParam", "Annotation", "AnnotationFileCitation", "AnnotationURLCitation", "AnnotationContainerFileCitation", "AnnotationFilePath", "Logprob", "LogprobTopLogprob", ] class AnnotationFileCitation(TypedDict, total=False): """A citation to a file.""" file_id: Required[str] """The ID of the file.""" filename: Required[str] """The filename of the file cited.""" index: Required[int] """The index of the file in the list of files.""" type: Required[Literal["file_citation"]] """The type of the file citation. Always `file_citation`.""" class AnnotationURLCitation(TypedDict, total=False): """A citation for a web resource used to generate a model response.""" end_index: Required[int] """The index of the last character of the URL citation in the message.""" start_index: Required[int] """The index of the first character of the URL citation in the message.""" title: Required[str] """The title of the web resource.""" type: Required[Literal["url_citation"]] """The type of the URL citation. Always `url_citation`.""" url: Required[str] """The URL of the web resource.""" class AnnotationContainerFileCitation(TypedDict, total=False): """A citation for a container file used to generate a model response.""" container_id: Required[str] """The ID of the container file.""" end_index: Required[int] """The index of the last character of the container file citation in the message.""" file_id: Required[str] """The ID of the file.""" filename: Required[str] """The filename of the container file cited.""" start_index: Required[int] """The index of the first character of the container file citation in the message.""" type: Required[Literal["container_file_citation"]] """The type of the container file citation. Always `container_file_citation`.""" class AnnotationFilePath(TypedDict, total=False): """A path to a file.""" file_id: Required[str] """The ID of the file.""" index: Required[int] """The index of the file in the list of files.""" type: Required[Literal["file_path"]] """The type of the file path. Always `file_path`.""" Annotation: TypeAlias = Union[ AnnotationFileCitation, AnnotationURLCitation, AnnotationContainerFileCitation, AnnotationFilePath ] class LogprobTopLogprob(TypedDict, total=False): """The top log probability of a token.""" token: Required[str] bytes: Required[Iterable[int]] logprob: Required[float] class Logprob(TypedDict, total=False): """The log probability of a token.""" token: Required[str] bytes: Required[Iterable[int]] logprob: Required[float] top_logprobs: Required[Iterable[LogprobTopLogprob]] class ResponseOutputTextParam(TypedDict, total=False): """A text output from the model.""" annotations: Required[Iterable[Annotation]] """The annotations of the text output.""" text: Required[str] """The text output from the model.""" type: Required[Literal["output_text"]] """The type of the output text. Always `output_text`.""" logprobs: Iterable[Logprob] ================================================ FILE: src/openai/types/responses/response_prompt.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, Union, Optional from typing_extensions import TypeAlias from ..._models import BaseModel from .response_input_file import ResponseInputFile from .response_input_text import ResponseInputText from .response_input_image import ResponseInputImage __all__ = ["ResponsePrompt", "Variables"] Variables: TypeAlias = Union[str, ResponseInputText, ResponseInputImage, ResponseInputFile] class ResponsePrompt(BaseModel): """ Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). """ id: str """The unique identifier of the prompt template to use.""" variables: Optional[Dict[str, Variables]] = None """Optional map of values to substitute in for variables in your prompt. The substitution values can either be strings, or other Response input types like images or files. """ version: Optional[str] = None """Optional version of the prompt template.""" ================================================ FILE: src/openai/types/responses/response_prompt_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Union, Optional from typing_extensions import Required, TypeAlias, TypedDict from .response_input_file_param import ResponseInputFileParam from .response_input_text_param import ResponseInputTextParam from .response_input_image_param import ResponseInputImageParam __all__ = ["ResponsePromptParam", "Variables"] Variables: TypeAlias = Union[str, ResponseInputTextParam, ResponseInputImageParam, ResponseInputFileParam] class ResponsePromptParam(TypedDict, total=False): """ Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). """ id: Required[str] """The unique identifier of the prompt template to use.""" variables: Optional[Dict[str, Variables]] """Optional map of values to substitute in for variables in your prompt. The substitution values can either be strings, or other Response input types like images or files. """ version: Optional[str] """Optional version of the prompt template.""" ================================================ FILE: src/openai/types/responses/response_queued_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .response import Response from ..._models import BaseModel __all__ = ["ResponseQueuedEvent"] class ResponseQueuedEvent(BaseModel): """Emitted when a response is queued and waiting to be processed.""" response: Response """The full response object that is queued.""" sequence_number: int """The sequence number for this event.""" type: Literal["response.queued"] """The type of the event. Always 'response.queued'.""" ================================================ FILE: src/openai/types/responses/response_reasoning_item.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseReasoningItem", "Summary", "Content"] class Summary(BaseModel): """A summary text from the model.""" text: str """A summary of the reasoning output from the model so far.""" type: Literal["summary_text"] """The type of the object. Always `summary_text`.""" class Content(BaseModel): """Reasoning text from the model.""" text: str """The reasoning text from the model.""" type: Literal["reasoning_text"] """The type of the reasoning text. Always `reasoning_text`.""" class ResponseReasoningItem(BaseModel): """ A description of the chain of thought used by a reasoning model while generating a response. Be sure to include these items in your `input` to the Responses API for subsequent turns of a conversation if you are manually [managing context](https://platform.openai.com/docs/guides/conversation-state). """ id: str """The unique identifier of the reasoning content.""" summary: List[Summary] """Reasoning summary content.""" type: Literal["reasoning"] """The type of the object. Always `reasoning`.""" content: Optional[List[Content]] = None """Reasoning text content.""" encrypted_content: Optional[str] = None """ The encrypted content of the reasoning item - populated when a response is generated with `reasoning.encrypted_content` in the `include` parameter. """ status: Optional[Literal["in_progress", "completed", "incomplete"]] = None """The status of the item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API. """ ================================================ FILE: src/openai/types/responses/response_reasoning_item_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Iterable, Optional from typing_extensions import Literal, Required, TypedDict __all__ = ["ResponseReasoningItemParam", "Summary", "Content"] class Summary(TypedDict, total=False): """A summary text from the model.""" text: Required[str] """A summary of the reasoning output from the model so far.""" type: Required[Literal["summary_text"]] """The type of the object. Always `summary_text`.""" class Content(TypedDict, total=False): """Reasoning text from the model.""" text: Required[str] """The reasoning text from the model.""" type: Required[Literal["reasoning_text"]] """The type of the reasoning text. Always `reasoning_text`.""" class ResponseReasoningItemParam(TypedDict, total=False): """ A description of the chain of thought used by a reasoning model while generating a response. Be sure to include these items in your `input` to the Responses API for subsequent turns of a conversation if you are manually [managing context](https://platform.openai.com/docs/guides/conversation-state). """ id: Required[str] """The unique identifier of the reasoning content.""" summary: Required[Iterable[Summary]] """Reasoning summary content.""" type: Required[Literal["reasoning"]] """The type of the object. Always `reasoning`.""" content: Iterable[Content] """Reasoning text content.""" encrypted_content: Optional[str] """ The encrypted content of the reasoning item - populated when a response is generated with `reasoning.encrypted_content` in the `include` parameter. """ status: Literal["in_progress", "completed", "incomplete"] """The status of the item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API. """ ================================================ FILE: src/openai/types/responses/response_reasoning_summary_part_added_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseReasoningSummaryPartAddedEvent", "Part"] class Part(BaseModel): """The summary part that was added.""" text: str """The text of the summary part.""" type: Literal["summary_text"] """The type of the summary part. Always `summary_text`.""" class ResponseReasoningSummaryPartAddedEvent(BaseModel): """Emitted when a new reasoning summary part is added.""" item_id: str """The ID of the item this summary part is associated with.""" output_index: int """The index of the output item this summary part is associated with.""" part: Part """The summary part that was added.""" sequence_number: int """The sequence number of this event.""" summary_index: int """The index of the summary part within the reasoning summary.""" type: Literal["response.reasoning_summary_part.added"] """The type of the event. Always `response.reasoning_summary_part.added`.""" ================================================ FILE: src/openai/types/responses/response_reasoning_summary_part_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseReasoningSummaryPartDoneEvent", "Part"] class Part(BaseModel): """The completed summary part.""" text: str """The text of the summary part.""" type: Literal["summary_text"] """The type of the summary part. Always `summary_text`.""" class ResponseReasoningSummaryPartDoneEvent(BaseModel): """Emitted when a reasoning summary part is completed.""" item_id: str """The ID of the item this summary part is associated with.""" output_index: int """The index of the output item this summary part is associated with.""" part: Part """The completed summary part.""" sequence_number: int """The sequence number of this event.""" summary_index: int """The index of the summary part within the reasoning summary.""" type: Literal["response.reasoning_summary_part.done"] """The type of the event. Always `response.reasoning_summary_part.done`.""" ================================================ FILE: src/openai/types/responses/response_reasoning_summary_text_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseReasoningSummaryTextDeltaEvent"] class ResponseReasoningSummaryTextDeltaEvent(BaseModel): """Emitted when a delta is added to a reasoning summary text.""" delta: str """The text delta that was added to the summary.""" item_id: str """The ID of the item this summary text delta is associated with.""" output_index: int """The index of the output item this summary text delta is associated with.""" sequence_number: int """The sequence number of this event.""" summary_index: int """The index of the summary part within the reasoning summary.""" type: Literal["response.reasoning_summary_text.delta"] """The type of the event. Always `response.reasoning_summary_text.delta`.""" ================================================ FILE: src/openai/types/responses/response_reasoning_summary_text_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseReasoningSummaryTextDoneEvent"] class ResponseReasoningSummaryTextDoneEvent(BaseModel): """Emitted when a reasoning summary text is completed.""" item_id: str """The ID of the item this summary text is associated with.""" output_index: int """The index of the output item this summary text is associated with.""" sequence_number: int """The sequence number of this event.""" summary_index: int """The index of the summary part within the reasoning summary.""" text: str """The full text of the completed reasoning summary.""" type: Literal["response.reasoning_summary_text.done"] """The type of the event. Always `response.reasoning_summary_text.done`.""" ================================================ FILE: src/openai/types/responses/response_reasoning_text_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseReasoningTextDeltaEvent"] class ResponseReasoningTextDeltaEvent(BaseModel): """Emitted when a delta is added to a reasoning text.""" content_index: int """The index of the reasoning content part this delta is associated with.""" delta: str """The text delta that was added to the reasoning content.""" item_id: str """The ID of the item this reasoning text delta is associated with.""" output_index: int """The index of the output item this reasoning text delta is associated with.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.reasoning_text.delta"] """The type of the event. Always `response.reasoning_text.delta`.""" ================================================ FILE: src/openai/types/responses/response_reasoning_text_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseReasoningTextDoneEvent"] class ResponseReasoningTextDoneEvent(BaseModel): """Emitted when a reasoning text is completed.""" content_index: int """The index of the reasoning content part.""" item_id: str """The ID of the item this reasoning text is associated with.""" output_index: int """The index of the output item this reasoning text is associated with.""" sequence_number: int """The sequence number of this event.""" text: str """The full text of the completed reasoning content.""" type: Literal["response.reasoning_text.done"] """The type of the event. Always `response.reasoning_text.done`.""" ================================================ FILE: src/openai/types/responses/response_refusal_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseRefusalDeltaEvent"] class ResponseRefusalDeltaEvent(BaseModel): """Emitted when there is a partial refusal text.""" content_index: int """The index of the content part that the refusal text is added to.""" delta: str """The refusal text that is added.""" item_id: str """The ID of the output item that the refusal text is added to.""" output_index: int """The index of the output item that the refusal text is added to.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.refusal.delta"] """The type of the event. Always `response.refusal.delta`.""" ================================================ FILE: src/openai/types/responses/response_refusal_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseRefusalDoneEvent"] class ResponseRefusalDoneEvent(BaseModel): """Emitted when refusal text is finalized.""" content_index: int """The index of the content part that the refusal text is finalized.""" item_id: str """The ID of the output item that the refusal text is finalized.""" output_index: int """The index of the output item that the refusal text is finalized.""" refusal: str """The refusal text that is finalized.""" sequence_number: int """The sequence number of this event.""" type: Literal["response.refusal.done"] """The type of the event. Always `response.refusal.done`.""" ================================================ FILE: src/openai/types/responses/response_retrieve_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List, Union from typing_extensions import Literal, Required, TypedDict from .response_includable import ResponseIncludable __all__ = ["ResponseRetrieveParamsBase", "ResponseRetrieveParamsNonStreaming", "ResponseRetrieveParamsStreaming"] class ResponseRetrieveParamsBase(TypedDict, total=False): include: List[ResponseIncludable] """Additional fields to include in the response. See the `include` parameter for Response creation above for more information. """ include_obfuscation: bool """When true, stream obfuscation will be enabled. Stream obfuscation adds random characters to an `obfuscation` field on streaming delta events to normalize payload sizes as a mitigation to certain side-channel attacks. These obfuscation fields are included by default, but add a small amount of overhead to the data stream. You can set `include_obfuscation` to false to optimize for bandwidth if you trust the network links between your application and the OpenAI API. """ starting_after: int """The sequence number of the event after which to start streaming.""" class ResponseRetrieveParamsNonStreaming(ResponseRetrieveParamsBase, total=False): stream: Literal[False] """ If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) for more information. """ class ResponseRetrieveParamsStreaming(ResponseRetrieveParamsBase): stream: Required[Literal[True]] """ If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) for more information. """ ResponseRetrieveParams = Union[ResponseRetrieveParamsNonStreaming, ResponseRetrieveParamsStreaming] ================================================ FILE: src/openai/types/responses/response_status.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["ResponseStatus"] ResponseStatus: TypeAlias = Literal["completed", "failed", "in_progress", "cancelled", "queued", "incomplete"] ================================================ FILE: src/openai/types/responses/response_stream_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from ..._utils import PropertyInfo from .response_error_event import ResponseErrorEvent from .response_failed_event import ResponseFailedEvent from .response_queued_event import ResponseQueuedEvent from .response_created_event import ResponseCreatedEvent from .response_completed_event import ResponseCompletedEvent from .response_text_done_event import ResponseTextDoneEvent from .response_audio_done_event import ResponseAudioDoneEvent from .response_incomplete_event import ResponseIncompleteEvent from .response_text_delta_event import ResponseTextDeltaEvent from .response_audio_delta_event import ResponseAudioDeltaEvent from .response_in_progress_event import ResponseInProgressEvent from .response_refusal_done_event import ResponseRefusalDoneEvent from .response_refusal_delta_event import ResponseRefusalDeltaEvent from .response_mcp_call_failed_event import ResponseMcpCallFailedEvent from .response_output_item_done_event import ResponseOutputItemDoneEvent from .response_content_part_done_event import ResponseContentPartDoneEvent from .response_output_item_added_event import ResponseOutputItemAddedEvent from .response_content_part_added_event import ResponseContentPartAddedEvent from .response_mcp_call_completed_event import ResponseMcpCallCompletedEvent from .response_reasoning_text_done_event import ResponseReasoningTextDoneEvent from .response_mcp_call_in_progress_event import ResponseMcpCallInProgressEvent from .response_reasoning_text_delta_event import ResponseReasoningTextDeltaEvent from .response_audio_transcript_done_event import ResponseAudioTranscriptDoneEvent from .response_mcp_list_tools_failed_event import ResponseMcpListToolsFailedEvent from .response_audio_transcript_delta_event import ResponseAudioTranscriptDeltaEvent from .response_mcp_call_arguments_done_event import ResponseMcpCallArgumentsDoneEvent from .response_image_gen_call_completed_event import ResponseImageGenCallCompletedEvent from .response_mcp_call_arguments_delta_event import ResponseMcpCallArgumentsDeltaEvent from .response_mcp_list_tools_completed_event import ResponseMcpListToolsCompletedEvent from .response_image_gen_call_generating_event import ResponseImageGenCallGeneratingEvent from .response_web_search_call_completed_event import ResponseWebSearchCallCompletedEvent from .response_web_search_call_searching_event import ResponseWebSearchCallSearchingEvent from .response_file_search_call_completed_event import ResponseFileSearchCallCompletedEvent from .response_file_search_call_searching_event import ResponseFileSearchCallSearchingEvent from .response_image_gen_call_in_progress_event import ResponseImageGenCallInProgressEvent from .response_mcp_list_tools_in_progress_event import ResponseMcpListToolsInProgressEvent from .response_custom_tool_call_input_done_event import ResponseCustomToolCallInputDoneEvent from .response_reasoning_summary_part_done_event import ResponseReasoningSummaryPartDoneEvent from .response_reasoning_summary_text_done_event import ResponseReasoningSummaryTextDoneEvent from .response_web_search_call_in_progress_event import ResponseWebSearchCallInProgressEvent from .response_custom_tool_call_input_delta_event import ResponseCustomToolCallInputDeltaEvent from .response_file_search_call_in_progress_event import ResponseFileSearchCallInProgressEvent from .response_function_call_arguments_done_event import ResponseFunctionCallArgumentsDoneEvent from .response_image_gen_call_partial_image_event import ResponseImageGenCallPartialImageEvent from .response_output_text_annotation_added_event import ResponseOutputTextAnnotationAddedEvent from .response_reasoning_summary_part_added_event import ResponseReasoningSummaryPartAddedEvent from .response_reasoning_summary_text_delta_event import ResponseReasoningSummaryTextDeltaEvent from .response_function_call_arguments_delta_event import ResponseFunctionCallArgumentsDeltaEvent from .response_code_interpreter_call_code_done_event import ResponseCodeInterpreterCallCodeDoneEvent from .response_code_interpreter_call_completed_event import ResponseCodeInterpreterCallCompletedEvent from .response_code_interpreter_call_code_delta_event import ResponseCodeInterpreterCallCodeDeltaEvent from .response_code_interpreter_call_in_progress_event import ResponseCodeInterpreterCallInProgressEvent from .response_code_interpreter_call_interpreting_event import ResponseCodeInterpreterCallInterpretingEvent __all__ = ["ResponseStreamEvent"] ResponseStreamEvent: TypeAlias = Annotated[ Union[ ResponseAudioDeltaEvent, ResponseAudioDoneEvent, ResponseAudioTranscriptDeltaEvent, ResponseAudioTranscriptDoneEvent, ResponseCodeInterpreterCallCodeDeltaEvent, ResponseCodeInterpreterCallCodeDoneEvent, ResponseCodeInterpreterCallCompletedEvent, ResponseCodeInterpreterCallInProgressEvent, ResponseCodeInterpreterCallInterpretingEvent, ResponseCompletedEvent, ResponseContentPartAddedEvent, ResponseContentPartDoneEvent, ResponseCreatedEvent, ResponseErrorEvent, ResponseFileSearchCallCompletedEvent, ResponseFileSearchCallInProgressEvent, ResponseFileSearchCallSearchingEvent, ResponseFunctionCallArgumentsDeltaEvent, ResponseFunctionCallArgumentsDoneEvent, ResponseInProgressEvent, ResponseFailedEvent, ResponseIncompleteEvent, ResponseOutputItemAddedEvent, ResponseOutputItemDoneEvent, ResponseReasoningSummaryPartAddedEvent, ResponseReasoningSummaryPartDoneEvent, ResponseReasoningSummaryTextDeltaEvent, ResponseReasoningSummaryTextDoneEvent, ResponseReasoningTextDeltaEvent, ResponseReasoningTextDoneEvent, ResponseRefusalDeltaEvent, ResponseRefusalDoneEvent, ResponseTextDeltaEvent, ResponseTextDoneEvent, ResponseWebSearchCallCompletedEvent, ResponseWebSearchCallInProgressEvent, ResponseWebSearchCallSearchingEvent, ResponseImageGenCallCompletedEvent, ResponseImageGenCallGeneratingEvent, ResponseImageGenCallInProgressEvent, ResponseImageGenCallPartialImageEvent, ResponseMcpCallArgumentsDeltaEvent, ResponseMcpCallArgumentsDoneEvent, ResponseMcpCallCompletedEvent, ResponseMcpCallFailedEvent, ResponseMcpCallInProgressEvent, ResponseMcpListToolsCompletedEvent, ResponseMcpListToolsFailedEvent, ResponseMcpListToolsInProgressEvent, ResponseOutputTextAnnotationAddedEvent, ResponseQueuedEvent, ResponseCustomToolCallInputDeltaEvent, ResponseCustomToolCallInputDoneEvent, ], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/types/responses/response_text_config.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel from .response_format_text_config import ResponseFormatTextConfig __all__ = ["ResponseTextConfig"] class ResponseTextConfig(BaseModel): """Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) """ format: Optional[ResponseFormatTextConfig] = None """An object specifying the format that the model must output. Configuring `{ "type": "json_schema" }` enables Structured Outputs, which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). The default format is `{ "type": "text" }` with no additional options. **Not recommended for gpt-4o and newer models:** Setting to `{ "type": "json_object" }` enables the older JSON mode, which ensures the message the model generates is valid JSON. Using `json_schema` is preferred for models that support it. """ verbosity: Optional[Literal["low", "medium", "high"]] = None """Constrains the verbosity of the model's response. Lower values will result in more concise responses, while higher values will result in more verbose responses. Currently supported values are `low`, `medium`, and `high`. """ ================================================ FILE: src/openai/types/responses/response_text_config_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Literal, TypedDict from .response_format_text_config_param import ResponseFormatTextConfigParam __all__ = ["ResponseTextConfigParam"] class ResponseTextConfigParam(TypedDict, total=False): """Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) """ format: ResponseFormatTextConfigParam """An object specifying the format that the model must output. Configuring `{ "type": "json_schema" }` enables Structured Outputs, which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). The default format is `{ "type": "text" }` with no additional options. **Not recommended for gpt-4o and newer models:** Setting to `{ "type": "json_object" }` enables the older JSON mode, which ensures the message the model generates is valid JSON. Using `json_schema` is preferred for models that support it. """ verbosity: Optional[Literal["low", "medium", "high"]] """Constrains the verbosity of the model's response. Lower values will result in more concise responses, while higher values will result in more verbose responses. Currently supported values are `low`, `medium`, and `high`. """ ================================================ FILE: src/openai/types/responses/response_text_delta_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseTextDeltaEvent", "Logprob", "LogprobTopLogprob"] class LogprobTopLogprob(BaseModel): token: Optional[str] = None """A possible text token.""" logprob: Optional[float] = None """The log probability of this token.""" class Logprob(BaseModel): """ A logprob is the logarithmic probability that the model assigns to producing a particular token at a given position in the sequence. Less-negative (higher) logprob values indicate greater model confidence in that token choice. """ token: str """A possible text token.""" logprob: float """The log probability of this token.""" top_logprobs: Optional[List[LogprobTopLogprob]] = None """The log probability of the top 20 most likely tokens.""" class ResponseTextDeltaEvent(BaseModel): """Emitted when there is an additional text delta.""" content_index: int """The index of the content part that the text delta was added to.""" delta: str """The text delta that was added.""" item_id: str """The ID of the output item that the text delta was added to.""" logprobs: List[Logprob] """The log probabilities of the tokens in the delta.""" output_index: int """The index of the output item that the text delta was added to.""" sequence_number: int """The sequence number for this event.""" type: Literal["response.output_text.delta"] """The type of the event. Always `response.output_text.delta`.""" ================================================ FILE: src/openai/types/responses/response_text_done_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseTextDoneEvent", "Logprob", "LogprobTopLogprob"] class LogprobTopLogprob(BaseModel): token: Optional[str] = None """A possible text token.""" logprob: Optional[float] = None """The log probability of this token.""" class Logprob(BaseModel): """ A logprob is the logarithmic probability that the model assigns to producing a particular token at a given position in the sequence. Less-negative (higher) logprob values indicate greater model confidence in that token choice. """ token: str """A possible text token.""" logprob: float """The log probability of this token.""" top_logprobs: Optional[List[LogprobTopLogprob]] = None """The log probability of the top 20 most likely tokens.""" class ResponseTextDoneEvent(BaseModel): """Emitted when text content is finalized.""" content_index: int """The index of the content part that the text content is finalized.""" item_id: str """The ID of the output item that the text content is finalized.""" logprobs: List[Logprob] """The log probabilities of the tokens in the delta.""" output_index: int """The index of the output item that the text content is finalized.""" sequence_number: int """The sequence number for this event.""" text: str """The text content that is finalized.""" type: Literal["response.output_text.done"] """The type of the event. Always `response.output_text.done`.""" ================================================ FILE: src/openai/types/responses/response_tool_search_call.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseToolSearchCall"] class ResponseToolSearchCall(BaseModel): id: str """The unique ID of the tool search call item.""" arguments: object """Arguments used for the tool search call.""" call_id: Optional[str] = None """The unique ID of the tool search call generated by the model.""" execution: Literal["server", "client"] """Whether tool search was executed by the server or by the client.""" status: Literal["in_progress", "completed", "incomplete"] """The status of the tool search call item that was recorded.""" type: Literal["tool_search_call"] """The type of the item. Always `tool_search_call`.""" created_by: Optional[str] = None """The identifier of the actor that created the item.""" ================================================ FILE: src/openai/types/responses/response_tool_search_output_item.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from .tool import Tool from ..._models import BaseModel __all__ = ["ResponseToolSearchOutputItem"] class ResponseToolSearchOutputItem(BaseModel): id: str """The unique ID of the tool search output item.""" call_id: Optional[str] = None """The unique ID of the tool search call generated by the model.""" execution: Literal["server", "client"] """Whether tool search was executed by the server or by the client.""" status: Literal["in_progress", "completed", "incomplete"] """The status of the tool search output item that was recorded.""" tools: List[Tool] """The loaded tool definitions returned by tool search.""" type: Literal["tool_search_output"] """The type of the item. Always `tool_search_output`.""" created_by: Optional[str] = None """The identifier of the actor that created the item.""" ================================================ FILE: src/openai/types/responses/response_tool_search_output_item_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from .tool import Tool from ..._models import BaseModel __all__ = ["ResponseToolSearchOutputItemParam"] class ResponseToolSearchOutputItemParam(BaseModel): tools: List[Tool] """The loaded tool definitions returned by the tool search output.""" type: Literal["tool_search_output"] """The item type. Always `tool_search_output`.""" id: Optional[str] = None """The unique ID of this tool search output.""" call_id: Optional[str] = None """The unique ID of the tool search call generated by the model.""" execution: Optional[Literal["server", "client"]] = None """Whether tool search was executed by the server or by the client.""" status: Optional[Literal["in_progress", "completed", "incomplete"]] = None """The status of the tool search output.""" ================================================ FILE: src/openai/types/responses/response_tool_search_output_item_param_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Iterable, Optional from typing_extensions import Literal, Required, TypedDict from .tool_param import ToolParam __all__ = ["ResponseToolSearchOutputItemParamParam"] class ResponseToolSearchOutputItemParamParam(TypedDict, total=False): tools: Required[Iterable[ToolParam]] """The loaded tool definitions returned by the tool search output.""" type: Required[Literal["tool_search_output"]] """The item type. Always `tool_search_output`.""" id: Optional[str] """The unique ID of this tool search output.""" call_id: Optional[str] """The unique ID of the tool search call generated by the model.""" execution: Literal["server", "client"] """Whether tool search was executed by the server or by the client.""" status: Optional[Literal["in_progress", "completed", "incomplete"]] """The status of the tool search output.""" ================================================ FILE: src/openai/types/responses/response_usage.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from ..._models import BaseModel __all__ = ["ResponseUsage", "InputTokensDetails", "OutputTokensDetails"] class InputTokensDetails(BaseModel): """A detailed breakdown of the input tokens.""" cached_tokens: int """The number of tokens that were retrieved from the cache. [More on prompt caching](https://platform.openai.com/docs/guides/prompt-caching). """ class OutputTokensDetails(BaseModel): """A detailed breakdown of the output tokens.""" reasoning_tokens: int """The number of reasoning tokens.""" class ResponseUsage(BaseModel): """ Represents token usage details including input tokens, output tokens, a breakdown of output tokens, and the total tokens used. """ input_tokens: int """The number of input tokens.""" input_tokens_details: InputTokensDetails """A detailed breakdown of the input tokens.""" output_tokens: int """The number of output tokens.""" output_tokens_details: OutputTokensDetails """A detailed breakdown of the output tokens.""" total_tokens: int """The total number of tokens used.""" ================================================ FILE: src/openai/types/responses/response_web_search_call_completed_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseWebSearchCallCompletedEvent"] class ResponseWebSearchCallCompletedEvent(BaseModel): """Emitted when a web search call is completed.""" item_id: str """Unique ID for the output item associated with the web search call.""" output_index: int """The index of the output item that the web search call is associated with.""" sequence_number: int """The sequence number of the web search call being processed.""" type: Literal["response.web_search_call.completed"] """The type of the event. Always `response.web_search_call.completed`.""" ================================================ FILE: src/openai/types/responses/response_web_search_call_in_progress_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseWebSearchCallInProgressEvent"] class ResponseWebSearchCallInProgressEvent(BaseModel): """Emitted when a web search call is initiated.""" item_id: str """Unique ID for the output item associated with the web search call.""" output_index: int """The index of the output item that the web search call is associated with.""" sequence_number: int """The sequence number of the web search call being processed.""" type: Literal["response.web_search_call.in_progress"] """The type of the event. Always `response.web_search_call.in_progress`.""" ================================================ FILE: src/openai/types/responses/response_web_search_call_searching_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseWebSearchCallSearchingEvent"] class ResponseWebSearchCallSearchingEvent(BaseModel): """Emitted when a web search call is executing.""" item_id: str """Unique ID for the output item associated with the web search call.""" output_index: int """The index of the output item that the web search call is associated with.""" sequence_number: int """The sequence number of the web search call being processed.""" type: Literal["response.web_search_call.searching"] """The type of the event. Always `response.web_search_call.searching`.""" ================================================ FILE: src/openai/types/responses/responses_client_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional from typing_extensions import Literal, TypeAlias from .tool import Tool from ..._models import BaseModel from .response_input import ResponseInput from .response_prompt import ResponsePrompt from .tool_choice_mcp import ToolChoiceMcp from ..shared.metadata import Metadata from ..shared.reasoning import Reasoning from .tool_choice_shell import ToolChoiceShell from .tool_choice_types import ToolChoiceTypes from .tool_choice_custom import ToolChoiceCustom from .response_includable import ResponseIncludable from .tool_choice_allowed import ToolChoiceAllowed from .tool_choice_options import ToolChoiceOptions from .response_text_config import ResponseTextConfig from .tool_choice_function import ToolChoiceFunction from ..shared.responses_model import ResponsesModel from .tool_choice_apply_patch import ToolChoiceApplyPatch from .response_conversation_param import ResponseConversationParam __all__ = ["ResponsesClientEvent", "ContextManagement", "Conversation", "StreamOptions", "ToolChoice"] class ContextManagement(BaseModel): type: str """The context management entry type. Currently only 'compaction' is supported.""" compact_threshold: Optional[int] = None """Token threshold at which compaction should be triggered for this entry.""" Conversation: TypeAlias = Union[str, ResponseConversationParam, None] class StreamOptions(BaseModel): """Options for streaming responses. Only set this when you set `stream: true`.""" include_obfuscation: Optional[bool] = None """When true, stream obfuscation will be enabled. Stream obfuscation adds random characters to an `obfuscation` field on streaming delta events to normalize payload sizes as a mitigation to certain side-channel attacks. These obfuscation fields are included by default, but add a small amount of overhead to the data stream. You can set `include_obfuscation` to false to optimize for bandwidth if you trust the network links between your application and the OpenAI API. """ ToolChoice: TypeAlias = Union[ ToolChoiceOptions, ToolChoiceAllowed, ToolChoiceTypes, ToolChoiceFunction, ToolChoiceMcp, ToolChoiceCustom, ToolChoiceApplyPatch, ToolChoiceShell, ] class ResponsesClientEvent(BaseModel): type: Literal["response.create"] """The type of the client event. Always `response.create`.""" background: Optional[bool] = None """ Whether to run the model response in the background. [Learn more](https://platform.openai.com/docs/guides/background). """ context_management: Optional[List[ContextManagement]] = None """Context management configuration for this request.""" conversation: Optional[Conversation] = None """The conversation that this response belongs to. Items from this conversation are prepended to `input_items` for this response request. Input items and output items from this response are automatically added to this conversation after this response completes. """ include: Optional[List[ResponseIncludable]] = None """Specify additional output data to include in the model response. Currently supported values are: - `web_search_call.action.sources`: Include the sources of the web search tool call. - `code_interpreter_call.outputs`: Includes the outputs of python code execution in code interpreter tool call items. - `computer_call_output.output.image_url`: Include image urls from the computer call output. - `file_search_call.results`: Include the search results of the file search tool call. - `message.input_image.image_url`: Include image urls from the input message. - `message.output_text.logprobs`: Include logprobs with assistant messages. - `reasoning.encrypted_content`: Includes an encrypted version of reasoning tokens in reasoning item outputs. This enables reasoning items to be used in multi-turn conversations when using the Responses API statelessly (like when the `store` parameter is set to `false`, or when an organization is enrolled in the zero data retention program). """ input: Union[str, ResponseInput, None] = None """Text, image, or file inputs to the model, used to generate a response. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Image inputs](https://platform.openai.com/docs/guides/images) - [File inputs](https://platform.openai.com/docs/guides/pdf-files) - [Conversation state](https://platform.openai.com/docs/guides/conversation-state) - [Function calling](https://platform.openai.com/docs/guides/function-calling) """ instructions: Optional[str] = None """A system (or developer) message inserted into the model's context. When using along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses. """ max_output_tokens: Optional[int] = None """ An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). """ max_tool_calls: Optional[int] = None """ The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored. """ metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ model: Optional[ResponsesModel] = None """Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. """ parallel_tool_calls: Optional[bool] = None """Whether to allow the model to run tool calls in parallel.""" previous_response_id: Optional[str] = None """The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://platform.openai.com/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`. """ prompt: Optional[ResponsePrompt] = None """ Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). """ prompt_cache_key: Optional[str] = None """ Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://platform.openai.com/docs/guides/prompt-caching). """ prompt_cache_retention: Optional[Literal["in-memory", "24h"]] = None """The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). """ reasoning: Optional[Reasoning] = None """**gpt-5 and o-series models only** Configuration options for [reasoning models](https://platform.openai.com/docs/guides/reasoning). """ safety_identifier: Optional[str] = None """ A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). """ service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] = None """Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier. - When not set, the default behavior is 'auto'. When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. """ store: Optional[bool] = None """Whether to store the generated model response for later retrieval via API.""" stream: Optional[bool] = None """ If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) for more information. """ stream_options: Optional[StreamOptions] = None """Options for streaming responses. Only set this when you set `stream: true`.""" temperature: Optional[float] = None """What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. """ text: Optional[ResponseTextConfig] = None """Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) """ tool_choice: Optional[ToolChoice] = None """ How the model should select which tool (or tools) to use when generating a response. See the `tools` parameter to see how to specify which tools the model can call. """ tools: Optional[List[Tool]] = None """An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. We support the following categories of tools: - **Built-in tools**: Tools that are provided by OpenAI that extend the model's capabilities, like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). - **MCP Tools**: Integrations with third-party systems via custom MCP servers or predefined connectors such as Google Drive and SharePoint. Learn more about [MCP Tools](https://platform.openai.com/docs/guides/tools-connectors-mcp). - **Function calls (custom tools)**: Functions that are defined by you, enabling the model to call your own code with strongly typed arguments and outputs. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). You can also use custom tools to call your own code. """ top_logprobs: Optional[int] = None """ An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. """ top_p: Optional[float] = None """ An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. """ truncation: Optional[Literal["auto", "disabled"]] = None """The truncation strategy to use for the model response. - `auto`: If the input to this Response exceeds the model's context window size, the model will truncate the response to fit the context window by dropping items from the beginning of the conversation. - `disabled` (default): If the input size will exceed the context window size for a model, the request will fail with a 400 error. """ user: Optional[str] = None """This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations. A stable identifier for your end-users. Used to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). """ ================================================ FILE: src/openai/types/responses/responses_client_event_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List, Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from .tool_param import ToolParam from .response_includable import ResponseIncludable from .tool_choice_options import ToolChoiceOptions from .response_input_param import ResponseInputParam from .response_prompt_param import ResponsePromptParam from .tool_choice_mcp_param import ToolChoiceMcpParam from ..shared_params.metadata import Metadata from .tool_choice_shell_param import ToolChoiceShellParam from .tool_choice_types_param import ToolChoiceTypesParam from ..shared_params.reasoning import Reasoning from .tool_choice_custom_param import ToolChoiceCustomParam from .tool_choice_allowed_param import ToolChoiceAllowedParam from .response_text_config_param import ResponseTextConfigParam from .tool_choice_function_param import ToolChoiceFunctionParam from .tool_choice_apply_patch_param import ToolChoiceApplyPatchParam from ..shared_params.responses_model import ResponsesModel from .response_conversation_param_param import ResponseConversationParamParam __all__ = ["ResponsesClientEventParam", "ContextManagement", "Conversation", "StreamOptions", "ToolChoice"] class ContextManagement(TypedDict, total=False): type: Required[str] """The context management entry type. Currently only 'compaction' is supported.""" compact_threshold: Optional[int] """Token threshold at which compaction should be triggered for this entry.""" Conversation: TypeAlias = Union[str, ResponseConversationParamParam] class StreamOptions(TypedDict, total=False): """Options for streaming responses. Only set this when you set `stream: true`.""" include_obfuscation: bool """When true, stream obfuscation will be enabled. Stream obfuscation adds random characters to an `obfuscation` field on streaming delta events to normalize payload sizes as a mitigation to certain side-channel attacks. These obfuscation fields are included by default, but add a small amount of overhead to the data stream. You can set `include_obfuscation` to false to optimize for bandwidth if you trust the network links between your application and the OpenAI API. """ ToolChoice: TypeAlias = Union[ ToolChoiceOptions, ToolChoiceAllowedParam, ToolChoiceTypesParam, ToolChoiceFunctionParam, ToolChoiceMcpParam, ToolChoiceCustomParam, ToolChoiceApplyPatchParam, ToolChoiceShellParam, ] class ResponsesClientEventParam(TypedDict, total=False): type: Required[Literal["response.create"]] """The type of the client event. Always `response.create`.""" background: Optional[bool] """ Whether to run the model response in the background. [Learn more](https://platform.openai.com/docs/guides/background). """ context_management: Optional[Iterable[ContextManagement]] """Context management configuration for this request.""" conversation: Optional[Conversation] """The conversation that this response belongs to. Items from this conversation are prepended to `input_items` for this response request. Input items and output items from this response are automatically added to this conversation after this response completes. """ include: Optional[List[ResponseIncludable]] """Specify additional output data to include in the model response. Currently supported values are: - `web_search_call.action.sources`: Include the sources of the web search tool call. - `code_interpreter_call.outputs`: Includes the outputs of python code execution in code interpreter tool call items. - `computer_call_output.output.image_url`: Include image urls from the computer call output. - `file_search_call.results`: Include the search results of the file search tool call. - `message.input_image.image_url`: Include image urls from the input message. - `message.output_text.logprobs`: Include logprobs with assistant messages. - `reasoning.encrypted_content`: Includes an encrypted version of reasoning tokens in reasoning item outputs. This enables reasoning items to be used in multi-turn conversations when using the Responses API statelessly (like when the `store` parameter is set to `false`, or when an organization is enrolled in the zero data retention program). """ input: Union[str, ResponseInputParam] """Text, image, or file inputs to the model, used to generate a response. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Image inputs](https://platform.openai.com/docs/guides/images) - [File inputs](https://platform.openai.com/docs/guides/pdf-files) - [Conversation state](https://platform.openai.com/docs/guides/conversation-state) - [Function calling](https://platform.openai.com/docs/guides/function-calling) """ instructions: Optional[str] """A system (or developer) message inserted into the model's context. When using along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses. """ max_output_tokens: Optional[int] """ An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). """ max_tool_calls: Optional[int] """ The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored. """ metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ model: ResponsesModel """Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare available models. """ parallel_tool_calls: Optional[bool] """Whether to allow the model to run tool calls in parallel.""" previous_response_id: Optional[str] """The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://platform.openai.com/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`. """ prompt: Optional[ResponsePromptParam] """ Reference to a prompt template and its variables. [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). """ prompt_cache_key: str """ Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://platform.openai.com/docs/guides/prompt-caching). """ prompt_cache_retention: Optional[Literal["in-memory", "24h"]] """The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). """ reasoning: Optional[Reasoning] """**gpt-5 and o-series models only** Configuration options for [reasoning models](https://platform.openai.com/docs/guides/reasoning). """ safety_identifier: str """ A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). """ service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] """Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier. - When not set, the default behavior is 'auto'. When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. """ store: Optional[bool] """Whether to store the generated model response for later retrieval via API.""" stream: Optional[bool] """ If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). See the [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) for more information. """ stream_options: Optional[StreamOptions] """Options for streaming responses. Only set this when you set `stream: true`.""" temperature: Optional[float] """What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both. """ text: ResponseTextConfigParam """Configuration options for a text response from the model. Can be plain text or structured JSON data. Learn more: - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) """ tool_choice: ToolChoice """ How the model should select which tool (or tools) to use when generating a response. See the `tools` parameter to see how to specify which tools the model can call. """ tools: Iterable[ToolParam] """An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter. We support the following categories of tools: - **Built-in tools**: Tools that are provided by OpenAI that extend the model's capabilities, like [web search](https://platform.openai.com/docs/guides/tools-web-search) or [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). - **MCP Tools**: Integrations with third-party systems via custom MCP servers or predefined connectors such as Google Drive and SharePoint. Learn more about [MCP Tools](https://platform.openai.com/docs/guides/tools-connectors-mcp). - **Function calls (custom tools)**: Functions that are defined by you, enabling the model to call your own code with strongly typed arguments and outputs. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling). You can also use custom tools to call your own code. """ top_logprobs: Optional[int] """ An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. """ top_p: Optional[float] """ An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both. """ truncation: Optional[Literal["auto", "disabled"]] """The truncation strategy to use for the model response. - `auto`: If the input to this Response exceeds the model's context window size, the model will truncate the response to fit the context window by dropping items from the beginning of the conversation. - `disabled` (default): If the input size will exceed the context window size for a model, the request will fail with a 400 error. """ user: str """This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations. A stable identifier for your end-users. Used to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). """ ================================================ FILE: src/openai/types/responses/responses_server_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from ..._utils import PropertyInfo from .response_error_event import ResponseErrorEvent from .response_failed_event import ResponseFailedEvent from .response_queued_event import ResponseQueuedEvent from .response_created_event import ResponseCreatedEvent from .response_completed_event import ResponseCompletedEvent from .response_text_done_event import ResponseTextDoneEvent from .response_audio_done_event import ResponseAudioDoneEvent from .response_incomplete_event import ResponseIncompleteEvent from .response_text_delta_event import ResponseTextDeltaEvent from .response_audio_delta_event import ResponseAudioDeltaEvent from .response_in_progress_event import ResponseInProgressEvent from .response_refusal_done_event import ResponseRefusalDoneEvent from .response_refusal_delta_event import ResponseRefusalDeltaEvent from .response_mcp_call_failed_event import ResponseMcpCallFailedEvent from .response_output_item_done_event import ResponseOutputItemDoneEvent from .response_content_part_done_event import ResponseContentPartDoneEvent from .response_output_item_added_event import ResponseOutputItemAddedEvent from .response_content_part_added_event import ResponseContentPartAddedEvent from .response_mcp_call_completed_event import ResponseMcpCallCompletedEvent from .response_reasoning_text_done_event import ResponseReasoningTextDoneEvent from .response_mcp_call_in_progress_event import ResponseMcpCallInProgressEvent from .response_reasoning_text_delta_event import ResponseReasoningTextDeltaEvent from .response_audio_transcript_done_event import ResponseAudioTranscriptDoneEvent from .response_mcp_list_tools_failed_event import ResponseMcpListToolsFailedEvent from .response_audio_transcript_delta_event import ResponseAudioTranscriptDeltaEvent from .response_mcp_call_arguments_done_event import ResponseMcpCallArgumentsDoneEvent from .response_image_gen_call_completed_event import ResponseImageGenCallCompletedEvent from .response_mcp_call_arguments_delta_event import ResponseMcpCallArgumentsDeltaEvent from .response_mcp_list_tools_completed_event import ResponseMcpListToolsCompletedEvent from .response_image_gen_call_generating_event import ResponseImageGenCallGeneratingEvent from .response_web_search_call_completed_event import ResponseWebSearchCallCompletedEvent from .response_web_search_call_searching_event import ResponseWebSearchCallSearchingEvent from .response_file_search_call_completed_event import ResponseFileSearchCallCompletedEvent from .response_file_search_call_searching_event import ResponseFileSearchCallSearchingEvent from .response_image_gen_call_in_progress_event import ResponseImageGenCallInProgressEvent from .response_mcp_list_tools_in_progress_event import ResponseMcpListToolsInProgressEvent from .response_custom_tool_call_input_done_event import ResponseCustomToolCallInputDoneEvent from .response_reasoning_summary_part_done_event import ResponseReasoningSummaryPartDoneEvent from .response_reasoning_summary_text_done_event import ResponseReasoningSummaryTextDoneEvent from .response_web_search_call_in_progress_event import ResponseWebSearchCallInProgressEvent from .response_custom_tool_call_input_delta_event import ResponseCustomToolCallInputDeltaEvent from .response_file_search_call_in_progress_event import ResponseFileSearchCallInProgressEvent from .response_function_call_arguments_done_event import ResponseFunctionCallArgumentsDoneEvent from .response_image_gen_call_partial_image_event import ResponseImageGenCallPartialImageEvent from .response_output_text_annotation_added_event import ResponseOutputTextAnnotationAddedEvent from .response_reasoning_summary_part_added_event import ResponseReasoningSummaryPartAddedEvent from .response_reasoning_summary_text_delta_event import ResponseReasoningSummaryTextDeltaEvent from .response_function_call_arguments_delta_event import ResponseFunctionCallArgumentsDeltaEvent from .response_code_interpreter_call_code_done_event import ResponseCodeInterpreterCallCodeDoneEvent from .response_code_interpreter_call_completed_event import ResponseCodeInterpreterCallCompletedEvent from .response_code_interpreter_call_code_delta_event import ResponseCodeInterpreterCallCodeDeltaEvent from .response_code_interpreter_call_in_progress_event import ResponseCodeInterpreterCallInProgressEvent from .response_code_interpreter_call_interpreting_event import ResponseCodeInterpreterCallInterpretingEvent __all__ = ["ResponsesServerEvent"] ResponsesServerEvent: TypeAlias = Annotated[ Union[ ResponseAudioDeltaEvent, ResponseAudioDoneEvent, ResponseAudioTranscriptDeltaEvent, ResponseAudioTranscriptDoneEvent, ResponseCodeInterpreterCallCodeDeltaEvent, ResponseCodeInterpreterCallCodeDoneEvent, ResponseCodeInterpreterCallCompletedEvent, ResponseCodeInterpreterCallInProgressEvent, ResponseCodeInterpreterCallInterpretingEvent, ResponseCompletedEvent, ResponseContentPartAddedEvent, ResponseContentPartDoneEvent, ResponseCreatedEvent, ResponseErrorEvent, ResponseFileSearchCallCompletedEvent, ResponseFileSearchCallInProgressEvent, ResponseFileSearchCallSearchingEvent, ResponseFunctionCallArgumentsDeltaEvent, ResponseFunctionCallArgumentsDoneEvent, ResponseInProgressEvent, ResponseFailedEvent, ResponseIncompleteEvent, ResponseOutputItemAddedEvent, ResponseOutputItemDoneEvent, ResponseReasoningSummaryPartAddedEvent, ResponseReasoningSummaryPartDoneEvent, ResponseReasoningSummaryTextDeltaEvent, ResponseReasoningSummaryTextDoneEvent, ResponseReasoningTextDeltaEvent, ResponseReasoningTextDoneEvent, ResponseRefusalDeltaEvent, ResponseRefusalDoneEvent, ResponseTextDeltaEvent, ResponseTextDoneEvent, ResponseWebSearchCallCompletedEvent, ResponseWebSearchCallInProgressEvent, ResponseWebSearchCallSearchingEvent, ResponseImageGenCallCompletedEvent, ResponseImageGenCallGeneratingEvent, ResponseImageGenCallInProgressEvent, ResponseImageGenCallPartialImageEvent, ResponseMcpCallArgumentsDeltaEvent, ResponseMcpCallArgumentsDoneEvent, ResponseMcpCallCompletedEvent, ResponseMcpCallFailedEvent, ResponseMcpCallInProgressEvent, ResponseMcpListToolsCompletedEvent, ResponseMcpListToolsFailedEvent, ResponseMcpListToolsInProgressEvent, ResponseOutputTextAnnotationAddedEvent, ResponseQueuedEvent, ResponseCustomToolCallInputDeltaEvent, ResponseCustomToolCallInputDoneEvent, ], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/types/responses/skill_reference.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["SkillReference"] class SkillReference(BaseModel): skill_id: str """The ID of the referenced skill.""" type: Literal["skill_reference"] """References a skill created with the /v1/skills endpoint.""" version: Optional[str] = None """Optional skill version. Use a positive integer or 'latest'. Omit for default.""" ================================================ FILE: src/openai/types/responses/skill_reference_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["SkillReferenceParam"] class SkillReferenceParam(TypedDict, total=False): skill_id: Required[str] """The ID of the referenced skill.""" type: Required[Literal["skill_reference"]] """References a skill created with the /v1/skills endpoint.""" version: str """Optional skill version. Use a positive integer or 'latest'. Omit for default.""" ================================================ FILE: src/openai/types/responses/tool.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from . import web_search_tool from ..._utils import PropertyInfo from ..._models import BaseModel from .custom_tool import CustomTool from .computer_tool import ComputerTool from .function_tool import FunctionTool from .namespace_tool import NamespaceTool from .web_search_tool import WebSearchTool from .apply_patch_tool import ApplyPatchTool from .file_search_tool import FileSearchTool from .tool_search_tool import ToolSearchTool from .function_shell_tool import FunctionShellTool from .web_search_preview_tool import WebSearchPreviewTool from .computer_use_preview_tool import ComputerUsePreviewTool from .container_network_policy_disabled import ContainerNetworkPolicyDisabled from .container_network_policy_allowlist import ContainerNetworkPolicyAllowlist __all__ = [ "Tool", "WebSearchTool", "Mcp", "McpAllowedTools", "McpAllowedToolsMcpToolFilter", "McpRequireApproval", "McpRequireApprovalMcpToolApprovalFilter", "McpRequireApprovalMcpToolApprovalFilterAlways", "McpRequireApprovalMcpToolApprovalFilterNever", "CodeInterpreter", "CodeInterpreterContainer", "CodeInterpreterContainerCodeInterpreterToolAuto", "CodeInterpreterContainerCodeInterpreterToolAutoNetworkPolicy", "ImageGeneration", "ImageGenerationInputImageMask", "LocalShell", ] WebSearchToolFilters = web_search_tool.Filters WebSearchToolUserLocation = web_search_tool.UserLocation class McpAllowedToolsMcpToolFilter(BaseModel): """A filter object to specify which tools are allowed.""" read_only: Optional[bool] = None """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: Optional[List[str]] = None """List of allowed tool names.""" McpAllowedTools: TypeAlias = Union[List[str], McpAllowedToolsMcpToolFilter, None] class McpRequireApprovalMcpToolApprovalFilterAlways(BaseModel): """A filter object to specify which tools are allowed.""" read_only: Optional[bool] = None """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: Optional[List[str]] = None """List of allowed tool names.""" class McpRequireApprovalMcpToolApprovalFilterNever(BaseModel): """A filter object to specify which tools are allowed.""" read_only: Optional[bool] = None """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: Optional[List[str]] = None """List of allowed tool names.""" class McpRequireApprovalMcpToolApprovalFilter(BaseModel): """Specify which of the MCP server's tools require approval. Can be `always`, `never`, or a filter object associated with tools that require approval. """ always: Optional[McpRequireApprovalMcpToolApprovalFilterAlways] = None """A filter object to specify which tools are allowed.""" never: Optional[McpRequireApprovalMcpToolApprovalFilterNever] = None """A filter object to specify which tools are allowed.""" McpRequireApproval: TypeAlias = Union[McpRequireApprovalMcpToolApprovalFilter, Literal["always", "never"], None] class Mcp(BaseModel): """ Give the model access to additional tools via remote Model Context Protocol (MCP) servers. [Learn more about MCP](https://platform.openai.com/docs/guides/tools-remote-mcp). """ server_label: str """A label for this MCP server, used to identify it in tool calls.""" type: Literal["mcp"] """The type of the MCP tool. Always `mcp`.""" allowed_tools: Optional[McpAllowedTools] = None """List of allowed tool names or a filter object.""" authorization: Optional[str] = None """ An OAuth access token that can be used with a remote MCP server, either with a custom MCP server URL or a service connector. Your application must handle the OAuth authorization flow and provide the token here. """ connector_id: Optional[ Literal[ "connector_dropbox", "connector_gmail", "connector_googlecalendar", "connector_googledrive", "connector_microsoftteams", "connector_outlookcalendar", "connector_outlookemail", "connector_sharepoint", ] ] = None """Identifier for service connectors, like those available in ChatGPT. One of `server_url` or `connector_id` must be provided. Learn more about service connectors [here](https://platform.openai.com/docs/guides/tools-remote-mcp#connectors). Currently supported `connector_id` values are: - Dropbox: `connector_dropbox` - Gmail: `connector_gmail` - Google Calendar: `connector_googlecalendar` - Google Drive: `connector_googledrive` - Microsoft Teams: `connector_microsoftteams` - Outlook Calendar: `connector_outlookcalendar` - Outlook Email: `connector_outlookemail` - SharePoint: `connector_sharepoint` """ defer_loading: Optional[bool] = None """Whether this MCP tool is deferred and discovered via tool search.""" headers: Optional[Dict[str, str]] = None """Optional HTTP headers to send to the MCP server. Use for authentication or other purposes. """ require_approval: Optional[McpRequireApproval] = None """Specify which of the MCP server's tools require approval.""" server_description: Optional[str] = None """Optional description of the MCP server, used to provide more context.""" server_url: Optional[str] = None """The URL for the MCP server. One of `server_url` or `connector_id` must be provided. """ CodeInterpreterContainerCodeInterpreterToolAutoNetworkPolicy: TypeAlias = Annotated[ Union[ContainerNetworkPolicyDisabled, ContainerNetworkPolicyAllowlist], PropertyInfo(discriminator="type") ] class CodeInterpreterContainerCodeInterpreterToolAuto(BaseModel): """Configuration for a code interpreter container. Optionally specify the IDs of the files to run the code on. """ type: Literal["auto"] """Always `auto`.""" file_ids: Optional[List[str]] = None """An optional list of uploaded files to make available to your code.""" memory_limit: Optional[Literal["1g", "4g", "16g", "64g"]] = None """The memory limit for the code interpreter container.""" network_policy: Optional[CodeInterpreterContainerCodeInterpreterToolAutoNetworkPolicy] = None """Network access policy for the container.""" CodeInterpreterContainer: TypeAlias = Union[str, CodeInterpreterContainerCodeInterpreterToolAuto] class CodeInterpreter(BaseModel): """A tool that runs Python code to help generate a response to a prompt.""" container: CodeInterpreterContainer """The code interpreter container. Can be a container ID or an object that specifies uploaded file IDs to make available to your code, along with an optional `memory_limit` setting. """ type: Literal["code_interpreter"] """The type of the code interpreter tool. Always `code_interpreter`.""" class ImageGenerationInputImageMask(BaseModel): """Optional mask for inpainting. Contains `image_url` (string, optional) and `file_id` (string, optional). """ file_id: Optional[str] = None """File ID for the mask image.""" image_url: Optional[str] = None """Base64-encoded mask image.""" class ImageGeneration(BaseModel): """A tool that generates images using the GPT image models.""" type: Literal["image_generation"] """The type of the image generation tool. Always `image_generation`.""" action: Optional[Literal["generate", "edit", "auto"]] = None """Whether to generate a new image or edit an existing image. Default: `auto`.""" background: Optional[Literal["transparent", "opaque", "auto"]] = None """Background type for the generated image. One of `transparent`, `opaque`, or `auto`. Default: `auto`. """ input_fidelity: Optional[Literal["high", "low"]] = None """ Control how much effort the model will exert to match the style and features, especially facial features, of input images. This parameter is only supported for `gpt-image-1` and `gpt-image-1.5` and later models, unsupported for `gpt-image-1-mini`. Supports `high` and `low`. Defaults to `low`. """ input_image_mask: Optional[ImageGenerationInputImageMask] = None """Optional mask for inpainting. Contains `image_url` (string, optional) and `file_id` (string, optional). """ model: Union[str, Literal["gpt-image-1", "gpt-image-1-mini", "gpt-image-1.5"], None] = None """The image generation model to use. Default: `gpt-image-1`.""" moderation: Optional[Literal["auto", "low"]] = None """Moderation level for the generated image. Default: `auto`.""" output_compression: Optional[int] = None """Compression level for the output image. Default: 100.""" output_format: Optional[Literal["png", "webp", "jpeg"]] = None """The output format of the generated image. One of `png`, `webp`, or `jpeg`. Default: `png`. """ partial_images: Optional[int] = None """ Number of partial images to generate in streaming mode, from 0 (default value) to 3. """ quality: Optional[Literal["low", "medium", "high", "auto"]] = None """The quality of the generated image. One of `low`, `medium`, `high`, or `auto`. Default: `auto`. """ size: Optional[Literal["1024x1024", "1024x1536", "1536x1024", "auto"]] = None """The size of the generated image. One of `1024x1024`, `1024x1536`, `1536x1024`, or `auto`. Default: `auto`. """ class LocalShell(BaseModel): """A tool that allows the model to execute shell commands in a local environment.""" type: Literal["local_shell"] """The type of the local shell tool. Always `local_shell`.""" Tool: TypeAlias = Annotated[ Union[ FunctionTool, FileSearchTool, ComputerTool, ComputerUsePreviewTool, WebSearchTool, Mcp, CodeInterpreter, ImageGeneration, LocalShell, FunctionShellTool, CustomTool, NamespaceTool, ToolSearchTool, WebSearchPreviewTool, ApplyPatchTool, ], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/types/responses/tool_choice_allowed.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ToolChoiceAllowed"] class ToolChoiceAllowed(BaseModel): """Constrains the tools available to the model to a pre-defined set.""" mode: Literal["auto", "required"] """Constrains the tools available to the model to a pre-defined set. `auto` allows the model to pick from among the allowed tools and generate a message. `required` requires the model to call one or more of the allowed tools. """ tools: List[Dict[str, object]] """A list of tool definitions that the model should be allowed to call. For the Responses API, the list of tool definitions might look like: ```json [ { "type": "function", "name": "get_weather" }, { "type": "mcp", "server_label": "deepwiki" }, { "type": "image_generation" } ] ``` """ type: Literal["allowed_tools"] """Allowed tool configuration type. Always `allowed_tools`.""" ================================================ FILE: src/openai/types/responses/tool_choice_allowed_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Iterable from typing_extensions import Literal, Required, TypedDict __all__ = ["ToolChoiceAllowedParam"] class ToolChoiceAllowedParam(TypedDict, total=False): """Constrains the tools available to the model to a pre-defined set.""" mode: Required[Literal["auto", "required"]] """Constrains the tools available to the model to a pre-defined set. `auto` allows the model to pick from among the allowed tools and generate a message. `required` requires the model to call one or more of the allowed tools. """ tools: Required[Iterable[Dict[str, object]]] """A list of tool definitions that the model should be allowed to call. For the Responses API, the list of tool definitions might look like: ```json [ { "type": "function", "name": "get_weather" }, { "type": "mcp", "server_label": "deepwiki" }, { "type": "image_generation" } ] ``` """ type: Required[Literal["allowed_tools"]] """Allowed tool configuration type. Always `allowed_tools`.""" ================================================ FILE: src/openai/types/responses/tool_choice_apply_patch.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ToolChoiceApplyPatch"] class ToolChoiceApplyPatch(BaseModel): """Forces the model to call the apply_patch tool when executing a tool call.""" type: Literal["apply_patch"] """The tool to call. Always `apply_patch`.""" ================================================ FILE: src/openai/types/responses/tool_choice_apply_patch_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ToolChoiceApplyPatchParam"] class ToolChoiceApplyPatchParam(TypedDict, total=False): """Forces the model to call the apply_patch tool when executing a tool call.""" type: Required[Literal["apply_patch"]] """The tool to call. Always `apply_patch`.""" ================================================ FILE: src/openai/types/responses/tool_choice_custom.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ToolChoiceCustom"] class ToolChoiceCustom(BaseModel): """Use this option to force the model to call a specific custom tool.""" name: str """The name of the custom tool to call.""" type: Literal["custom"] """For custom tool calling, the type is always `custom`.""" ================================================ FILE: src/openai/types/responses/tool_choice_custom_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ToolChoiceCustomParam"] class ToolChoiceCustomParam(TypedDict, total=False): """Use this option to force the model to call a specific custom tool.""" name: Required[str] """The name of the custom tool to call.""" type: Required[Literal["custom"]] """For custom tool calling, the type is always `custom`.""" ================================================ FILE: src/openai/types/responses/tool_choice_function.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ToolChoiceFunction"] class ToolChoiceFunction(BaseModel): """Use this option to force the model to call a specific function.""" name: str """The name of the function to call.""" type: Literal["function"] """For function calling, the type is always `function`.""" ================================================ FILE: src/openai/types/responses/tool_choice_function_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ToolChoiceFunctionParam"] class ToolChoiceFunctionParam(TypedDict, total=False): """Use this option to force the model to call a specific function.""" name: Required[str] """The name of the function to call.""" type: Required[Literal["function"]] """For function calling, the type is always `function`.""" ================================================ FILE: src/openai/types/responses/tool_choice_mcp.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ToolChoiceMcp"] class ToolChoiceMcp(BaseModel): """ Use this option to force the model to call a specific tool on a remote MCP server. """ server_label: str """The label of the MCP server to use.""" type: Literal["mcp"] """For MCP tools, the type is always `mcp`.""" name: Optional[str] = None """The name of the tool to call on the server.""" ================================================ FILE: src/openai/types/responses/tool_choice_mcp_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Literal, Required, TypedDict __all__ = ["ToolChoiceMcpParam"] class ToolChoiceMcpParam(TypedDict, total=False): """ Use this option to force the model to call a specific tool on a remote MCP server. """ server_label: Required[str] """The label of the MCP server to use.""" type: Required[Literal["mcp"]] """For MCP tools, the type is always `mcp`.""" name: Optional[str] """The name of the tool to call on the server.""" ================================================ FILE: src/openai/types/responses/tool_choice_options.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["ToolChoiceOptions"] ToolChoiceOptions: TypeAlias = Literal["none", "auto", "required"] ================================================ FILE: src/openai/types/responses/tool_choice_shell.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ToolChoiceShell"] class ToolChoiceShell(BaseModel): """Forces the model to call the shell tool when a tool call is required.""" type: Literal["shell"] """The tool to call. Always `shell`.""" ================================================ FILE: src/openai/types/responses/tool_choice_shell_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ToolChoiceShellParam"] class ToolChoiceShellParam(TypedDict, total=False): """Forces the model to call the shell tool when a tool call is required.""" type: Required[Literal["shell"]] """The tool to call. Always `shell`.""" ================================================ FILE: src/openai/types/responses/tool_choice_types.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ToolChoiceTypes"] class ToolChoiceTypes(BaseModel): """ Indicates that the model should use a built-in tool to generate a response. [Learn more about built-in tools](https://platform.openai.com/docs/guides/tools). """ type: Literal[ "file_search", "web_search_preview", "computer", "computer_use_preview", "computer_use", "web_search_preview_2025_03_11", "image_generation", "code_interpreter", ] """The type of hosted tool the model should to use. Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). Allowed values are: - `file_search` - `web_search_preview` - `computer` - `computer_use_preview` - `computer_use` - `code_interpreter` - `image_generation` """ ================================================ FILE: src/openai/types/responses/tool_choice_types_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ToolChoiceTypesParam"] class ToolChoiceTypesParam(TypedDict, total=False): """ Indicates that the model should use a built-in tool to generate a response. [Learn more about built-in tools](https://platform.openai.com/docs/guides/tools). """ type: Required[ Literal[ "file_search", "web_search_preview", "computer", "computer_use_preview", "computer_use", "web_search_preview_2025_03_11", "image_generation", "code_interpreter", ] ] """The type of hosted tool the model should to use. Learn more about [built-in tools](https://platform.openai.com/docs/guides/tools). Allowed values are: - `file_search` - `web_search_preview` - `computer` - `computer_use_preview` - `computer_use` - `code_interpreter` - `image_generation` """ ================================================ FILE: src/openai/types/responses/tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Union, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from . import web_search_tool_param from ..chat import ChatCompletionFunctionToolParam from ..._types import SequenceNotStr from .custom_tool_param import CustomToolParam from .computer_tool_param import ComputerToolParam from .function_tool_param import FunctionToolParam from .namespace_tool_param import NamespaceToolParam from .web_search_tool_param import WebSearchToolParam from .apply_patch_tool_param import ApplyPatchToolParam from .file_search_tool_param import FileSearchToolParam from .tool_search_tool_param import ToolSearchToolParam from .function_shell_tool_param import FunctionShellToolParam from .web_search_preview_tool_param import WebSearchPreviewToolParam from .computer_use_preview_tool_param import ComputerUsePreviewToolParam from .container_network_policy_disabled_param import ContainerNetworkPolicyDisabledParam from .container_network_policy_allowlist_param import ContainerNetworkPolicyAllowlistParam __all__ = [ "ToolParam", "Mcp", "McpAllowedTools", "McpAllowedToolsMcpToolFilter", "McpRequireApproval", "McpRequireApprovalMcpToolApprovalFilter", "McpRequireApprovalMcpToolApprovalFilterAlways", "McpRequireApprovalMcpToolApprovalFilterNever", "CodeInterpreter", "CodeInterpreterContainer", "CodeInterpreterContainerCodeInterpreterToolAuto", "CodeInterpreterContainerCodeInterpreterToolAutoNetworkPolicy", "ImageGeneration", "ImageGenerationInputImageMask", "LocalShell", ] WebSearchTool = web_search_tool_param.WebSearchToolParam WebSearchToolFilters = web_search_tool_param.Filters WebSearchToolUserLocation = web_search_tool_param.UserLocation class McpAllowedToolsMcpToolFilter(TypedDict, total=False): """A filter object to specify which tools are allowed.""" read_only: bool """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: SequenceNotStr[str] """List of allowed tool names.""" McpAllowedTools: TypeAlias = Union[SequenceNotStr[str], McpAllowedToolsMcpToolFilter] class McpRequireApprovalMcpToolApprovalFilterAlways(TypedDict, total=False): """A filter object to specify which tools are allowed.""" read_only: bool """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: SequenceNotStr[str] """List of allowed tool names.""" class McpRequireApprovalMcpToolApprovalFilterNever(TypedDict, total=False): """A filter object to specify which tools are allowed.""" read_only: bool """Indicates whether or not a tool modifies data or is read-only. If an MCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), it will match this filter. """ tool_names: SequenceNotStr[str] """List of allowed tool names.""" class McpRequireApprovalMcpToolApprovalFilter(TypedDict, total=False): """Specify which of the MCP server's tools require approval. Can be `always`, `never`, or a filter object associated with tools that require approval. """ always: McpRequireApprovalMcpToolApprovalFilterAlways """A filter object to specify which tools are allowed.""" never: McpRequireApprovalMcpToolApprovalFilterNever """A filter object to specify which tools are allowed.""" McpRequireApproval: TypeAlias = Union[McpRequireApprovalMcpToolApprovalFilter, Literal["always", "never"]] class Mcp(TypedDict, total=False): """ Give the model access to additional tools via remote Model Context Protocol (MCP) servers. [Learn more about MCP](https://platform.openai.com/docs/guides/tools-remote-mcp). """ server_label: Required[str] """A label for this MCP server, used to identify it in tool calls.""" type: Required[Literal["mcp"]] """The type of the MCP tool. Always `mcp`.""" allowed_tools: Optional[McpAllowedTools] """List of allowed tool names or a filter object.""" authorization: str """ An OAuth access token that can be used with a remote MCP server, either with a custom MCP server URL or a service connector. Your application must handle the OAuth authorization flow and provide the token here. """ connector_id: Literal[ "connector_dropbox", "connector_gmail", "connector_googlecalendar", "connector_googledrive", "connector_microsoftteams", "connector_outlookcalendar", "connector_outlookemail", "connector_sharepoint", ] """Identifier for service connectors, like those available in ChatGPT. One of `server_url` or `connector_id` must be provided. Learn more about service connectors [here](https://platform.openai.com/docs/guides/tools-remote-mcp#connectors). Currently supported `connector_id` values are: - Dropbox: `connector_dropbox` - Gmail: `connector_gmail` - Google Calendar: `connector_googlecalendar` - Google Drive: `connector_googledrive` - Microsoft Teams: `connector_microsoftteams` - Outlook Calendar: `connector_outlookcalendar` - Outlook Email: `connector_outlookemail` - SharePoint: `connector_sharepoint` """ defer_loading: bool """Whether this MCP tool is deferred and discovered via tool search.""" headers: Optional[Dict[str, str]] """Optional HTTP headers to send to the MCP server. Use for authentication or other purposes. """ require_approval: Optional[McpRequireApproval] """Specify which of the MCP server's tools require approval.""" server_description: str """Optional description of the MCP server, used to provide more context.""" server_url: str """The URL for the MCP server. One of `server_url` or `connector_id` must be provided. """ CodeInterpreterContainerCodeInterpreterToolAutoNetworkPolicy: TypeAlias = Union[ ContainerNetworkPolicyDisabledParam, ContainerNetworkPolicyAllowlistParam ] class CodeInterpreterContainerCodeInterpreterToolAuto(TypedDict, total=False): """Configuration for a code interpreter container. Optionally specify the IDs of the files to run the code on. """ type: Required[Literal["auto"]] """Always `auto`.""" file_ids: SequenceNotStr[str] """An optional list of uploaded files to make available to your code.""" memory_limit: Optional[Literal["1g", "4g", "16g", "64g"]] """The memory limit for the code interpreter container.""" network_policy: CodeInterpreterContainerCodeInterpreterToolAutoNetworkPolicy """Network access policy for the container.""" CodeInterpreterContainer: TypeAlias = Union[str, CodeInterpreterContainerCodeInterpreterToolAuto] class CodeInterpreter(TypedDict, total=False): """A tool that runs Python code to help generate a response to a prompt.""" container: Required[CodeInterpreterContainer] """The code interpreter container. Can be a container ID or an object that specifies uploaded file IDs to make available to your code, along with an optional `memory_limit` setting. """ type: Required[Literal["code_interpreter"]] """The type of the code interpreter tool. Always `code_interpreter`.""" class ImageGenerationInputImageMask(TypedDict, total=False): """Optional mask for inpainting. Contains `image_url` (string, optional) and `file_id` (string, optional). """ file_id: str """File ID for the mask image.""" image_url: str """Base64-encoded mask image.""" class ImageGeneration(TypedDict, total=False): """A tool that generates images using the GPT image models.""" type: Required[Literal["image_generation"]] """The type of the image generation tool. Always `image_generation`.""" action: Literal["generate", "edit", "auto"] """Whether to generate a new image or edit an existing image. Default: `auto`.""" background: Literal["transparent", "opaque", "auto"] """Background type for the generated image. One of `transparent`, `opaque`, or `auto`. Default: `auto`. """ input_fidelity: Optional[Literal["high", "low"]] """ Control how much effort the model will exert to match the style and features, especially facial features, of input images. This parameter is only supported for `gpt-image-1` and `gpt-image-1.5` and later models, unsupported for `gpt-image-1-mini`. Supports `high` and `low`. Defaults to `low`. """ input_image_mask: ImageGenerationInputImageMask """Optional mask for inpainting. Contains `image_url` (string, optional) and `file_id` (string, optional). """ model: Union[str, Literal["gpt-image-1", "gpt-image-1-mini", "gpt-image-1.5"]] """The image generation model to use. Default: `gpt-image-1`.""" moderation: Literal["auto", "low"] """Moderation level for the generated image. Default: `auto`.""" output_compression: int """Compression level for the output image. Default: 100.""" output_format: Literal["png", "webp", "jpeg"] """The output format of the generated image. One of `png`, `webp`, or `jpeg`. Default: `png`. """ partial_images: int """ Number of partial images to generate in streaming mode, from 0 (default value) to 3. """ quality: Literal["low", "medium", "high", "auto"] """The quality of the generated image. One of `low`, `medium`, `high`, or `auto`. Default: `auto`. """ size: Literal["1024x1024", "1024x1536", "1536x1024", "auto"] """The size of the generated image. One of `1024x1024`, `1024x1536`, `1536x1024`, or `auto`. Default: `auto`. """ class LocalShell(TypedDict, total=False): """A tool that allows the model to execute shell commands in a local environment.""" type: Required[Literal["local_shell"]] """The type of the local shell tool. Always `local_shell`.""" ToolParam: TypeAlias = Union[ FunctionToolParam, FileSearchToolParam, ComputerToolParam, ComputerUsePreviewToolParam, WebSearchToolParam, Mcp, CodeInterpreter, ImageGeneration, LocalShell, FunctionShellToolParam, CustomToolParam, NamespaceToolParam, ToolSearchToolParam, WebSearchPreviewToolParam, ApplyPatchToolParam, ] ParseableToolParam: TypeAlias = Union[ToolParam, ChatCompletionFunctionToolParam] ================================================ FILE: src/openai/types/responses/tool_search_tool.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ToolSearchTool"] class ToolSearchTool(BaseModel): """Hosted or BYOT tool search configuration for deferred tools.""" type: Literal["tool_search"] """The type of the tool. Always `tool_search`.""" description: Optional[str] = None """Description shown to the model for a client-executed tool search tool.""" execution: Optional[Literal["server", "client"]] = None """Whether tool search is executed by the server or by the client.""" parameters: Optional[object] = None """Parameter schema for a client-executed tool search tool.""" ================================================ FILE: src/openai/types/responses/tool_search_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Literal, Required, TypedDict __all__ = ["ToolSearchToolParam"] class ToolSearchToolParam(TypedDict, total=False): """Hosted or BYOT tool search configuration for deferred tools.""" type: Required[Literal["tool_search"]] """The type of the tool. Always `tool_search`.""" description: Optional[str] """Description shown to the model for a client-executed tool search tool.""" execution: Literal["server", "client"] """Whether tool search is executed by the server or by the client.""" parameters: Optional[object] """Parameter schema for a client-executed tool search tool.""" ================================================ FILE: src/openai/types/responses/web_search_preview_tool.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["WebSearchPreviewTool", "UserLocation"] class UserLocation(BaseModel): """The user's location.""" type: Literal["approximate"] """The type of location approximation. Always `approximate`.""" city: Optional[str] = None """Free text input for the city of the user, e.g. `San Francisco`.""" country: Optional[str] = None """ The two-letter [ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1) of the user, e.g. `US`. """ region: Optional[str] = None """Free text input for the region of the user, e.g. `California`.""" timezone: Optional[str] = None """ The [IANA timezone](https://timeapi.io/documentation/iana-timezones) of the user, e.g. `America/Los_Angeles`. """ class WebSearchPreviewTool(BaseModel): """This tool searches the web for relevant results to use in a response. Learn more about the [web search tool](https://platform.openai.com/docs/guides/tools-web-search). """ type: Literal["web_search_preview", "web_search_preview_2025_03_11"] """The type of the web search tool. One of `web_search_preview` or `web_search_preview_2025_03_11`. """ search_content_types: Optional[List[Literal["text", "image"]]] = None search_context_size: Optional[Literal["low", "medium", "high"]] = None """High level guidance for the amount of context window space to use for the search. One of `low`, `medium`, or `high`. `medium` is the default. """ user_location: Optional[UserLocation] = None """The user's location.""" ================================================ FILE: src/openai/types/responses/web_search_preview_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import List, Optional from typing_extensions import Literal, Required, TypedDict __all__ = ["WebSearchPreviewToolParam", "UserLocation"] class UserLocation(TypedDict, total=False): """The user's location.""" type: Required[Literal["approximate"]] """The type of location approximation. Always `approximate`.""" city: Optional[str] """Free text input for the city of the user, e.g. `San Francisco`.""" country: Optional[str] """ The two-letter [ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1) of the user, e.g. `US`. """ region: Optional[str] """Free text input for the region of the user, e.g. `California`.""" timezone: Optional[str] """ The [IANA timezone](https://timeapi.io/documentation/iana-timezones) of the user, e.g. `America/Los_Angeles`. """ class WebSearchPreviewToolParam(TypedDict, total=False): """This tool searches the web for relevant results to use in a response. Learn more about the [web search tool](https://platform.openai.com/docs/guides/tools-web-search). """ type: Required[Literal["web_search_preview", "web_search_preview_2025_03_11"]] """The type of the web search tool. One of `web_search_preview` or `web_search_preview_2025_03_11`. """ search_content_types: List[Literal["text", "image"]] search_context_size: Literal["low", "medium", "high"] """High level guidance for the amount of context window space to use for the search. One of `low`, `medium`, or `high`. `medium` is the default. """ user_location: Optional[UserLocation] """The user's location.""" ================================================ FILE: src/openai/types/responses/web_search_tool.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["WebSearchTool", "Filters", "UserLocation"] class Filters(BaseModel): """Filters for the search.""" allowed_domains: Optional[List[str]] = None """Allowed domains for the search. If not provided, all domains are allowed. Subdomains of the provided domains are allowed as well. Example: `["pubmed.ncbi.nlm.nih.gov"]` """ class UserLocation(BaseModel): """The approximate location of the user.""" city: Optional[str] = None """Free text input for the city of the user, e.g. `San Francisco`.""" country: Optional[str] = None """ The two-letter [ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1) of the user, e.g. `US`. """ region: Optional[str] = None """Free text input for the region of the user, e.g. `California`.""" timezone: Optional[str] = None """ The [IANA timezone](https://timeapi.io/documentation/iana-timezones) of the user, e.g. `America/Los_Angeles`. """ type: Optional[Literal["approximate"]] = None """The type of location approximation. Always `approximate`.""" class WebSearchTool(BaseModel): """Search the Internet for sources related to the prompt. Learn more about the [web search tool](https://platform.openai.com/docs/guides/tools-web-search). """ type: Literal["web_search", "web_search_2025_08_26"] """The type of the web search tool. One of `web_search` or `web_search_2025_08_26`. """ filters: Optional[Filters] = None """Filters for the search.""" search_context_size: Optional[Literal["low", "medium", "high"]] = None """High level guidance for the amount of context window space to use for the search. One of `low`, `medium`, or `high`. `medium` is the default. """ user_location: Optional[UserLocation] = None """The approximate location of the user.""" ================================================ FILE: src/openai/types/responses/web_search_tool_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Literal, Required, TypedDict from ..._types import SequenceNotStr __all__ = ["WebSearchToolParam", "Filters", "UserLocation"] class Filters(TypedDict, total=False): """Filters for the search.""" allowed_domains: Optional[SequenceNotStr[str]] """Allowed domains for the search. If not provided, all domains are allowed. Subdomains of the provided domains are allowed as well. Example: `["pubmed.ncbi.nlm.nih.gov"]` """ class UserLocation(TypedDict, total=False): """The approximate location of the user.""" city: Optional[str] """Free text input for the city of the user, e.g. `San Francisco`.""" country: Optional[str] """ The two-letter [ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1) of the user, e.g. `US`. """ region: Optional[str] """Free text input for the region of the user, e.g. `California`.""" timezone: Optional[str] """ The [IANA timezone](https://timeapi.io/documentation/iana-timezones) of the user, e.g. `America/Los_Angeles`. """ type: Literal["approximate"] """The type of location approximation. Always `approximate`.""" class WebSearchToolParam(TypedDict, total=False): """Search the Internet for sources related to the prompt. Learn more about the [web search tool](https://platform.openai.com/docs/guides/tools-web-search). """ type: Required[Literal["web_search", "web_search_2025_08_26"]] """The type of the web search tool. One of `web_search` or `web_search_2025_08_26`. """ filters: Optional[Filters] """Filters for the search.""" search_context_size: Literal["low", "medium", "high"] """High level guidance for the amount of context window space to use for the search. One of `low`, `medium`, or `high`. `medium` is the default. """ user_location: Optional[UserLocation] """The approximate location of the user.""" ================================================ FILE: src/openai/types/shared/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .metadata import Metadata as Metadata from .reasoning import Reasoning as Reasoning from .all_models import AllModels as AllModels from .chat_model import ChatModel as ChatModel from .error_object import ErrorObject as ErrorObject from .compound_filter import CompoundFilter as CompoundFilter from .responses_model import ResponsesModel as ResponsesModel from .reasoning_effort import ReasoningEffort as ReasoningEffort from .comparison_filter import ComparisonFilter as ComparisonFilter from .function_definition import FunctionDefinition as FunctionDefinition from .function_parameters import FunctionParameters as FunctionParameters from .response_format_text import ResponseFormatText as ResponseFormatText from .custom_tool_input_format import CustomToolInputFormat as CustomToolInputFormat from .response_format_json_object import ResponseFormatJSONObject as ResponseFormatJSONObject from .response_format_json_schema import ResponseFormatJSONSchema as ResponseFormatJSONSchema from .response_format_text_python import ResponseFormatTextPython as ResponseFormatTextPython from .response_format_text_grammar import ResponseFormatTextGrammar as ResponseFormatTextGrammar ================================================ FILE: src/openai/types/shared/all_models.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Literal, TypeAlias from .chat_model import ChatModel __all__ = ["AllModels"] AllModels: TypeAlias = Union[ str, ChatModel, Literal[ "o1-pro", "o1-pro-2025-03-19", "o3-pro", "o3-pro-2025-06-10", "o3-deep-research", "o3-deep-research-2025-06-26", "o4-mini-deep-research", "o4-mini-deep-research-2025-06-26", "computer-use-preview", "computer-use-preview-2025-03-11", "gpt-5-codex", "gpt-5-pro", "gpt-5-pro-2025-10-06", "gpt-5.1-codex-max", ], ] ================================================ FILE: src/openai/types/shared/chat_model.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["ChatModel"] ChatModel: TypeAlias = Literal[ "gpt-5.4", "gpt-5.4-mini", "gpt-5.4-nano", "gpt-5.4-mini-2026-03-17", "gpt-5.4-nano-2026-03-17", "gpt-5.3-chat-latest", "gpt-5.2", "gpt-5.2-2025-12-11", "gpt-5.2-chat-latest", "gpt-5.2-pro", "gpt-5.2-pro-2025-12-11", "gpt-5.1", "gpt-5.1-2025-11-13", "gpt-5.1-codex", "gpt-5.1-mini", "gpt-5.1-chat-latest", "gpt-5", "gpt-5-mini", "gpt-5-nano", "gpt-5-2025-08-07", "gpt-5-mini-2025-08-07", "gpt-5-nano-2025-08-07", "gpt-5-chat-latest", "gpt-4.1", "gpt-4.1-mini", "gpt-4.1-nano", "gpt-4.1-2025-04-14", "gpt-4.1-mini-2025-04-14", "gpt-4.1-nano-2025-04-14", "o4-mini", "o4-mini-2025-04-16", "o3", "o3-2025-04-16", "o3-mini", "o3-mini-2025-01-31", "o1", "o1-2024-12-17", "o1-preview", "o1-preview-2024-09-12", "o1-mini", "o1-mini-2024-09-12", "gpt-4o", "gpt-4o-2024-11-20", "gpt-4o-2024-08-06", "gpt-4o-2024-05-13", "gpt-4o-audio-preview", "gpt-4o-audio-preview-2024-10-01", "gpt-4o-audio-preview-2024-12-17", "gpt-4o-audio-preview-2025-06-03", "gpt-4o-mini-audio-preview", "gpt-4o-mini-audio-preview-2024-12-17", "gpt-4o-search-preview", "gpt-4o-mini-search-preview", "gpt-4o-search-preview-2025-03-11", "gpt-4o-mini-search-preview-2025-03-11", "chatgpt-4o-latest", "codex-mini-latest", "gpt-4o-mini", "gpt-4o-mini-2024-07-18", "gpt-4-turbo", "gpt-4-turbo-2024-04-09", "gpt-4-0125-preview", "gpt-4-turbo-preview", "gpt-4-1106-preview", "gpt-4-vision-preview", "gpt-4", "gpt-4-0314", "gpt-4-0613", "gpt-4-32k", "gpt-4-32k-0314", "gpt-4-32k-0613", "gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-3.5-turbo-0301", "gpt-3.5-turbo-0613", "gpt-3.5-turbo-1106", "gpt-3.5-turbo-0125", "gpt-3.5-turbo-16k-0613", ] ================================================ FILE: src/openai/types/shared/comparison_filter.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ComparisonFilter"] class ComparisonFilter(BaseModel): """ A filter used to compare a specified attribute key to a given value using a defined comparison operation. """ key: str """The key to compare against the value.""" type: Literal["eq", "ne", "gt", "gte", "lt", "lte", "in", "nin"] """ Specifies the comparison operator: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `in`, `nin`. - `eq`: equals - `ne`: not equal - `gt`: greater than - `gte`: greater than or equal - `lt`: less than - `lte`: less than or equal - `in`: in - `nin`: not in """ value: Union[str, float, bool, List[Union[str, float]]] """ The value to compare against the attribute key; supports string, number, or boolean types. """ ================================================ FILE: src/openai/types/shared/compound_filter.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union from typing_extensions import Literal, TypeAlias from ..._models import BaseModel from .comparison_filter import ComparisonFilter __all__ = ["CompoundFilter", "Filter"] Filter: TypeAlias = Union[ComparisonFilter, object] class CompoundFilter(BaseModel): """Combine multiple filters using `and` or `or`.""" filters: List[Filter] """Array of filters to combine. Items can be `ComparisonFilter` or `CompoundFilter`. """ type: Literal["and", "or"] """Type of operation: `and` or `or`.""" ================================================ FILE: src/openai/types/shared/custom_tool_input_format.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Literal, Annotated, TypeAlias from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = ["CustomToolInputFormat", "Text", "Grammar"] class Text(BaseModel): """Unconstrained free-form text.""" type: Literal["text"] """Unconstrained text format. Always `text`.""" class Grammar(BaseModel): """A grammar defined by the user.""" definition: str """The grammar definition.""" syntax: Literal["lark", "regex"] """The syntax of the grammar definition. One of `lark` or `regex`.""" type: Literal["grammar"] """Grammar format. Always `grammar`.""" CustomToolInputFormat: TypeAlias = Annotated[Union[Text, Grammar], PropertyInfo(discriminator="type")] ================================================ FILE: src/openai/types/shared/error_object.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from ..._models import BaseModel __all__ = ["ErrorObject"] class ErrorObject(BaseModel): code: Optional[str] = None message: str param: Optional[str] = None type: str ================================================ FILE: src/openai/types/shared/function_definition.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from ..._models import BaseModel from .function_parameters import FunctionParameters __all__ = ["FunctionDefinition"] class FunctionDefinition(BaseModel): name: str """The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64. """ description: Optional[str] = None """ A description of what the function does, used by the model to choose when and how to call the function. """ parameters: Optional[FunctionParameters] = None """The parameters the functions accepts, described as a JSON Schema object. See the [guide](https://platform.openai.com/docs/guides/function-calling) for examples, and the [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for documentation about the format. Omitting `parameters` defines a function with an empty parameter list. """ strict: Optional[bool] = None """Whether to enable strict schema adherence when generating the function call. If set to true, the model will follow the exact schema defined in the `parameters` field. Only a subset of JSON Schema is supported when `strict` is `true`. Learn more about Structured Outputs in the [function calling guide](https://platform.openai.com/docs/guides/function-calling). """ ================================================ FILE: src/openai/types/shared/function_parameters.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict from typing_extensions import TypeAlias __all__ = ["FunctionParameters"] FunctionParameters: TypeAlias = Dict[str, object] ================================================ FILE: src/openai/types/shared/metadata.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict from typing_extensions import TypeAlias __all__ = ["Metadata"] Metadata: TypeAlias = Dict[str, str] ================================================ FILE: src/openai/types/shared/reasoning.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel from .reasoning_effort import ReasoningEffort __all__ = ["Reasoning"] class Reasoning(BaseModel): """**gpt-5 and o-series models only** Configuration options for [reasoning models](https://platform.openai.com/docs/guides/reasoning). """ effort: Optional[ReasoningEffort] = None """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ generate_summary: Optional[Literal["auto", "concise", "detailed"]] = None """**Deprecated:** use `summary` instead. A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process. One of `auto`, `concise`, or `detailed`. """ summary: Optional[Literal["auto", "concise", "detailed"]] = None """A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process. One of `auto`, `concise`, or `detailed`. `concise` is supported for `computer-use-preview` models and all reasoning models after `gpt-5`. """ ================================================ FILE: src/openai/types/shared/reasoning_effort.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal, TypeAlias __all__ = ["ReasoningEffort"] ReasoningEffort: TypeAlias = Optional[Literal["none", "minimal", "low", "medium", "high", "xhigh"]] ================================================ FILE: src/openai/types/shared/response_format_json_object.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseFormatJSONObject"] class ResponseFormatJSONObject(BaseModel): """JSON object response format. An older method of generating JSON responses. Using `json_schema` is recommended for models that support it. Note that the model will not generate JSON without a system or user message instructing it to do so. """ type: Literal["json_object"] """The type of response format being defined. Always `json_object`.""" ================================================ FILE: src/openai/types/shared/response_format_json_schema.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, Optional from typing_extensions import Literal from pydantic import Field as FieldInfo from ..._models import BaseModel __all__ = ["ResponseFormatJSONSchema", "JSONSchema"] class JSONSchema(BaseModel): """Structured Outputs configuration options, including a JSON Schema.""" name: str """The name of the response format. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64. """ description: Optional[str] = None """ A description of what the response format is for, used by the model to determine how to respond in the format. """ schema_: Optional[Dict[str, object]] = FieldInfo(alias="schema", default=None) """ The schema for the response format, described as a JSON Schema object. Learn how to build JSON schemas [here](https://json-schema.org/). """ strict: Optional[bool] = None """ Whether to enable strict schema adherence when generating the output. If set to true, the model will always follow the exact schema defined in the `schema` field. Only a subset of JSON Schema is supported when `strict` is `true`. To learn more, read the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). """ class ResponseFormatJSONSchema(BaseModel): """JSON Schema response format. Used to generate structured JSON responses. Learn more about [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs). """ json_schema: JSONSchema """Structured Outputs configuration options, including a JSON Schema.""" type: Literal["json_schema"] """The type of response format being defined. Always `json_schema`.""" ================================================ FILE: src/openai/types/shared/response_format_text.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseFormatText"] class ResponseFormatText(BaseModel): """Default response format. Used to generate text responses.""" type: Literal["text"] """The type of response format being defined. Always `text`.""" ================================================ FILE: src/openai/types/shared/response_format_text_grammar.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseFormatTextGrammar"] class ResponseFormatTextGrammar(BaseModel): """ A custom grammar for the model to follow when generating text. Learn more in the [custom grammars guide](https://platform.openai.com/docs/guides/custom-grammars). """ grammar: str """The custom grammar for the model to follow.""" type: Literal["grammar"] """The type of response format being defined. Always `grammar`.""" ================================================ FILE: src/openai/types/shared/response_format_text_python.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseFormatTextPython"] class ResponseFormatTextPython(BaseModel): """Configure the model to generate valid Python code. See the [custom grammars guide](https://platform.openai.com/docs/guides/custom-grammars) for more details. """ type: Literal["python"] """The type of response format being defined. Always `python`.""" ================================================ FILE: src/openai/types/shared/responses_model.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Literal, TypeAlias from .chat_model import ChatModel __all__ = ["ResponsesModel"] ResponsesModel: TypeAlias = Union[ str, ChatModel, Literal[ "o1-pro", "o1-pro-2025-03-19", "o3-pro", "o3-pro-2025-06-10", "o3-deep-research", "o3-deep-research-2025-06-26", "o4-mini-deep-research", "o4-mini-deep-research-2025-06-26", "computer-use-preview", "computer-use-preview-2025-03-11", "gpt-5-codex", "gpt-5-pro", "gpt-5-pro-2025-10-06", "gpt-5.1-codex-max", ], ] ================================================ FILE: src/openai/types/shared_params/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .metadata import Metadata as Metadata from .reasoning import Reasoning as Reasoning from .chat_model import ChatModel as ChatModel from .compound_filter import CompoundFilter as CompoundFilter from .responses_model import ResponsesModel as ResponsesModel from .reasoning_effort import ReasoningEffort as ReasoningEffort from .comparison_filter import ComparisonFilter as ComparisonFilter from .function_definition import FunctionDefinition as FunctionDefinition from .function_parameters import FunctionParameters as FunctionParameters from .response_format_text import ResponseFormatText as ResponseFormatText from .custom_tool_input_format import CustomToolInputFormat as CustomToolInputFormat from .response_format_json_object import ResponseFormatJSONObject as ResponseFormatJSONObject from .response_format_json_schema import ResponseFormatJSONSchema as ResponseFormatJSONSchema ================================================ FILE: src/openai/types/shared_params/chat_model.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypeAlias __all__ = ["ChatModel"] ChatModel: TypeAlias = Literal[ "gpt-5.4", "gpt-5.4-mini", "gpt-5.4-nano", "gpt-5.4-mini-2026-03-17", "gpt-5.4-nano-2026-03-17", "gpt-5.3-chat-latest", "gpt-5.2", "gpt-5.2-2025-12-11", "gpt-5.2-chat-latest", "gpt-5.2-pro", "gpt-5.2-pro-2025-12-11", "gpt-5.1", "gpt-5.1-2025-11-13", "gpt-5.1-codex", "gpt-5.1-mini", "gpt-5.1-chat-latest", "gpt-5", "gpt-5-mini", "gpt-5-nano", "gpt-5-2025-08-07", "gpt-5-mini-2025-08-07", "gpt-5-nano-2025-08-07", "gpt-5-chat-latest", "gpt-4.1", "gpt-4.1-mini", "gpt-4.1-nano", "gpt-4.1-2025-04-14", "gpt-4.1-mini-2025-04-14", "gpt-4.1-nano-2025-04-14", "o4-mini", "o4-mini-2025-04-16", "o3", "o3-2025-04-16", "o3-mini", "o3-mini-2025-01-31", "o1", "o1-2024-12-17", "o1-preview", "o1-preview-2024-09-12", "o1-mini", "o1-mini-2024-09-12", "gpt-4o", "gpt-4o-2024-11-20", "gpt-4o-2024-08-06", "gpt-4o-2024-05-13", "gpt-4o-audio-preview", "gpt-4o-audio-preview-2024-10-01", "gpt-4o-audio-preview-2024-12-17", "gpt-4o-audio-preview-2025-06-03", "gpt-4o-mini-audio-preview", "gpt-4o-mini-audio-preview-2024-12-17", "gpt-4o-search-preview", "gpt-4o-mini-search-preview", "gpt-4o-search-preview-2025-03-11", "gpt-4o-mini-search-preview-2025-03-11", "chatgpt-4o-latest", "codex-mini-latest", "gpt-4o-mini", "gpt-4o-mini-2024-07-18", "gpt-4-turbo", "gpt-4-turbo-2024-04-09", "gpt-4-0125-preview", "gpt-4-turbo-preview", "gpt-4-1106-preview", "gpt-4-vision-preview", "gpt-4", "gpt-4-0314", "gpt-4-0613", "gpt-4-32k", "gpt-4-32k-0314", "gpt-4-32k-0613", "gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-3.5-turbo-0301", "gpt-3.5-turbo-0613", "gpt-3.5-turbo-1106", "gpt-3.5-turbo-0125", "gpt-3.5-turbo-16k-0613", ] ================================================ FILE: src/openai/types/shared_params/comparison_filter.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, Required, TypedDict from ..._types import SequenceNotStr __all__ = ["ComparisonFilter"] class ComparisonFilter(TypedDict, total=False): """ A filter used to compare a specified attribute key to a given value using a defined comparison operation. """ key: Required[str] """The key to compare against the value.""" type: Required[Literal["eq", "ne", "gt", "gte", "lt", "lte", "in", "nin"]] """ Specifies the comparison operator: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `in`, `nin`. - `eq`: equals - `ne`: not equal - `gt`: greater than - `gte`: greater than or equal - `lt`: less than - `lte`: less than or equal - `in`: in - `nin`: not in """ value: Required[Union[str, float, bool, SequenceNotStr[Union[str, float]]]] """ The value to compare against the attribute key; supports string, number, or boolean types. """ ================================================ FILE: src/openai/types/shared_params/compound_filter.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union, Iterable from typing_extensions import Literal, Required, TypeAlias, TypedDict from .comparison_filter import ComparisonFilter __all__ = ["CompoundFilter", "Filter"] Filter: TypeAlias = Union[ComparisonFilter, object] class CompoundFilter(TypedDict, total=False): """Combine multiple filters using `and` or `or`.""" filters: Required[Iterable[Filter]] """Array of filters to combine. Items can be `ComparisonFilter` or `CompoundFilter`. """ type: Required[Literal["and", "or"]] """Type of operation: `and` or `or`.""" ================================================ FILE: src/openai/types/shared_params/custom_tool_input_format.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, Required, TypeAlias, TypedDict __all__ = ["CustomToolInputFormat", "Text", "Grammar"] class Text(TypedDict, total=False): """Unconstrained free-form text.""" type: Required[Literal["text"]] """Unconstrained text format. Always `text`.""" class Grammar(TypedDict, total=False): """A grammar defined by the user.""" definition: Required[str] """The grammar definition.""" syntax: Required[Literal["lark", "regex"]] """The syntax of the grammar definition. One of `lark` or `regex`.""" type: Required[Literal["grammar"]] """Grammar format. Always `grammar`.""" CustomToolInputFormat: TypeAlias = Union[Text, Grammar] ================================================ FILE: src/openai/types/shared_params/function_definition.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Required, TypedDict from .function_parameters import FunctionParameters __all__ = ["FunctionDefinition"] class FunctionDefinition(TypedDict, total=False): name: Required[str] """The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64. """ description: str """ A description of what the function does, used by the model to choose when and how to call the function. """ parameters: FunctionParameters """The parameters the functions accepts, described as a JSON Schema object. See the [guide](https://platform.openai.com/docs/guides/function-calling) for examples, and the [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for documentation about the format. Omitting `parameters` defines a function with an empty parameter list. """ strict: Optional[bool] """Whether to enable strict schema adherence when generating the function call. If set to true, the model will follow the exact schema defined in the `parameters` field. Only a subset of JSON Schema is supported when `strict` is `true`. Learn more about Structured Outputs in the [function calling guide](https://platform.openai.com/docs/guides/function-calling). """ ================================================ FILE: src/openai/types/shared_params/function_parameters.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict from typing_extensions import TypeAlias __all__ = ["FunctionParameters"] FunctionParameters: TypeAlias = Dict[str, object] ================================================ FILE: src/openai/types/shared_params/metadata.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict from typing_extensions import TypeAlias __all__ = ["Metadata"] Metadata: TypeAlias = Dict[str, str] ================================================ FILE: src/openai/types/shared_params/reasoning.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Literal, TypedDict from ..shared.reasoning_effort import ReasoningEffort __all__ = ["Reasoning"] class Reasoning(TypedDict, total=False): """**gpt-5 and o-series models only** Configuration options for [reasoning models](https://platform.openai.com/docs/guides/reasoning). """ effort: Optional[ReasoningEffort] """ Constrains effort on reasoning for [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response. - `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1. - All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`. - The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort. - `xhigh` is supported for all models after `gpt-5.1-codex-max`. """ generate_summary: Optional[Literal["auto", "concise", "detailed"]] """**Deprecated:** use `summary` instead. A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process. One of `auto`, `concise`, or `detailed`. """ summary: Optional[Literal["auto", "concise", "detailed"]] """A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process. One of `auto`, `concise`, or `detailed`. `concise` is supported for `computer-use-preview` models and all reasoning models after `gpt-5`. """ ================================================ FILE: src/openai/types/shared_params/reasoning_effort.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Literal, TypeAlias __all__ = ["ReasoningEffort"] ReasoningEffort: TypeAlias = Optional[Literal["none", "minimal", "low", "medium", "high", "xhigh"]] ================================================ FILE: src/openai/types/shared_params/response_format_json_object.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ResponseFormatJSONObject"] class ResponseFormatJSONObject(TypedDict, total=False): """JSON object response format. An older method of generating JSON responses. Using `json_schema` is recommended for models that support it. Note that the model will not generate JSON without a system or user message instructing it to do so. """ type: Required[Literal["json_object"]] """The type of response format being defined. Always `json_object`.""" ================================================ FILE: src/openai/types/shared_params/response_format_json_schema.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Optional from typing_extensions import Literal, Required, TypedDict __all__ = ["ResponseFormatJSONSchema", "JSONSchema"] class JSONSchema(TypedDict, total=False): """Structured Outputs configuration options, including a JSON Schema.""" name: Required[str] """The name of the response format. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64. """ description: str """ A description of what the response format is for, used by the model to determine how to respond in the format. """ schema: Dict[str, object] """ The schema for the response format, described as a JSON Schema object. Learn how to build JSON schemas [here](https://json-schema.org/). """ strict: Optional[bool] """ Whether to enable strict schema adherence when generating the output. If set to true, the model will always follow the exact schema defined in the `schema` field. Only a subset of JSON Schema is supported when `strict` is `true`. To learn more, read the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). """ class ResponseFormatJSONSchema(TypedDict, total=False): """JSON Schema response format. Used to generate structured JSON responses. Learn more about [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs). """ json_schema: Required[JSONSchema] """Structured Outputs configuration options, including a JSON Schema.""" type: Required[Literal["json_schema"]] """The type of response format being defined. Always `json_schema`.""" ================================================ FILE: src/openai/types/shared_params/response_format_text.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["ResponseFormatText"] class ResponseFormatText(TypedDict, total=False): """Default response format. Used to generate text responses.""" type: Required[Literal["text"]] """The type of response format being defined. Always `text`.""" ================================================ FILE: src/openai/types/shared_params/responses_model.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, TypeAlias from ..shared.chat_model import ChatModel __all__ = ["ResponsesModel"] ResponsesModel: TypeAlias = Union[ str, ChatModel, Literal[ "o1-pro", "o1-pro-2025-03-19", "o3-pro", "o3-pro-2025-06-10", "o3-deep-research", "o3-deep-research-2025-06-26", "o4-mini-deep-research", "o4-mini-deep-research-2025-06-26", "computer-use-preview", "computer-use-preview-2025-03-11", "gpt-5-codex", "gpt-5-pro", "gpt-5-pro-2025-10-06", "gpt-5.1-codex-max", ], ] ================================================ FILE: src/openai/types/skill.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .._models import BaseModel __all__ = ["Skill"] class Skill(BaseModel): id: str """Unique identifier for the skill.""" created_at: int """Unix timestamp (seconds) for when the skill was created.""" default_version: str """Default version for the skill.""" description: str """Description of the skill.""" latest_version: str """Latest version for the skill.""" name: str """Name of the skill.""" object: Literal["skill"] """The object type, which is `skill`.""" ================================================ FILE: src/openai/types/skill_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import TypedDict from .._types import FileTypes, SequenceNotStr __all__ = ["SkillCreateParams"] class SkillCreateParams(TypedDict, total=False): files: Union[SequenceNotStr[FileTypes], FileTypes] """Skill files to upload (directory upload) or a single zip file.""" ================================================ FILE: src/openai/types/skill_list.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from .skill import Skill from .._models import BaseModel __all__ = ["SkillList"] class SkillList(BaseModel): data: List[Skill] """A list of items""" first_id: Optional[str] = None """The ID of the first item in the list.""" has_more: bool """Whether there are more items available.""" last_id: Optional[str] = None """The ID of the last item in the list.""" object: Literal["list"] """The type of object returned, must be `list`.""" ================================================ FILE: src/openai/types/skill_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["SkillListParams"] class SkillListParams(TypedDict, total=False): after: str """Identifier for the last item from the previous pagination request""" limit: int """Number of items to retrieve""" order: Literal["asc", "desc"] """Sort order of results by timestamp. Use `asc` for ascending order or `desc` for descending order. """ ================================================ FILE: src/openai/types/skill_update_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Required, TypedDict __all__ = ["SkillUpdateParams"] class SkillUpdateParams(TypedDict, total=False): default_version: Required[str] """The skill version number to set as default.""" ================================================ FILE: src/openai/types/skills/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .skill_version import SkillVersion as SkillVersion from .skill_version_list import SkillVersionList as SkillVersionList from .version_list_params import VersionListParams as VersionListParams from .deleted_skill_version import DeletedSkillVersion as DeletedSkillVersion from .version_create_params import VersionCreateParams as VersionCreateParams ================================================ FILE: src/openai/types/skills/deleted_skill_version.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["DeletedSkillVersion"] class DeletedSkillVersion(BaseModel): id: str deleted: bool object: Literal["skill.version.deleted"] version: str """The deleted skill version.""" ================================================ FILE: src/openai/types/skills/skill_version.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["SkillVersion"] class SkillVersion(BaseModel): id: str """Unique identifier for the skill version.""" created_at: int """Unix timestamp (seconds) for when the version was created.""" description: str """Description of the skill version.""" name: str """Name of the skill version.""" object: Literal["skill.version"] """The object type, which is `skill.version`.""" skill_id: str """Identifier of the skill for this version.""" version: str """Version number for this skill.""" ================================================ FILE: src/openai/types/skills/skill_version_list.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel from .skill_version import SkillVersion __all__ = ["SkillVersionList"] class SkillVersionList(BaseModel): data: List[SkillVersion] """A list of items""" first_id: Optional[str] = None """The ID of the first item in the list.""" has_more: bool """Whether there are more items available.""" last_id: Optional[str] = None """The ID of the last item in the list.""" object: Literal["list"] """The type of object returned, must be `list`.""" ================================================ FILE: src/openai/types/skills/version_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import TypedDict from ..._types import FileTypes, SequenceNotStr __all__ = ["VersionCreateParams"] class VersionCreateParams(TypedDict, total=False): default: bool """Whether to set this version as the default.""" files: Union[SequenceNotStr[FileTypes], FileTypes] """Skill files to upload (directory upload) or a single zip file.""" ================================================ FILE: src/openai/types/skills/version_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["VersionListParams"] class VersionListParams(TypedDict, total=False): after: str """The skill version ID to start after.""" limit: int """Number of versions to retrieve.""" order: Literal["asc", "desc"] """Sort order of results by version number.""" ================================================ FILE: src/openai/types/skills/versions/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations ================================================ FILE: src/openai/types/static_file_chunking_strategy.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .._models import BaseModel __all__ = ["StaticFileChunkingStrategy"] class StaticFileChunkingStrategy(BaseModel): chunk_overlap_tokens: int """The number of tokens that overlap between chunks. The default value is `400`. Note that the overlap must not exceed half of `max_chunk_size_tokens`. """ max_chunk_size_tokens: int """The maximum number of tokens in each chunk. The default value is `800`. The minimum value is `100` and the maximum value is `4096`. """ ================================================ FILE: src/openai/types/static_file_chunking_strategy_object.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .._models import BaseModel from .static_file_chunking_strategy import StaticFileChunkingStrategy __all__ = ["StaticFileChunkingStrategyObject"] class StaticFileChunkingStrategyObject(BaseModel): static: StaticFileChunkingStrategy type: Literal["static"] """Always `static`.""" ================================================ FILE: src/openai/types/static_file_chunking_strategy_object_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict from .static_file_chunking_strategy_param import StaticFileChunkingStrategyParam __all__ = ["StaticFileChunkingStrategyObjectParam"] class StaticFileChunkingStrategyObjectParam(TypedDict, total=False): """Customize your own chunking strategy by setting chunk size and chunk overlap.""" static: Required[StaticFileChunkingStrategyParam] type: Required[Literal["static"]] """Always `static`.""" ================================================ FILE: src/openai/types/static_file_chunking_strategy_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Required, TypedDict __all__ = ["StaticFileChunkingStrategyParam"] class StaticFileChunkingStrategyParam(TypedDict, total=False): chunk_overlap_tokens: Required[int] """The number of tokens that overlap between chunks. The default value is `400`. Note that the overlap must not exceed half of `max_chunk_size_tokens`. """ max_chunk_size_tokens: Required[int] """The maximum number of tokens in each chunk. The default value is `800`. The minimum value is `100` and the maximum value is `4096`. """ ================================================ FILE: src/openai/types/upload.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from .._models import BaseModel from .file_object import FileObject __all__ = ["Upload"] class Upload(BaseModel): """The Upload object can accept byte chunks in the form of Parts.""" id: str """The Upload unique identifier, which can be referenced in API endpoints.""" bytes: int """The intended number of bytes to be uploaded.""" created_at: int """The Unix timestamp (in seconds) for when the Upload was created.""" expires_at: int """The Unix timestamp (in seconds) for when the Upload will expire.""" filename: str """The name of the file to be uploaded.""" object: Literal["upload"] """The object type, which is always "upload".""" purpose: str """The intended purpose of the file. [Please refer here](https://platform.openai.com/docs/api-reference/files/object#files/object-purpose) for acceptable values. """ status: Literal["pending", "completed", "cancelled", "expired"] """The status of the Upload.""" file: Optional[FileObject] = None """The `File` object represents a document that has been uploaded to OpenAI.""" ================================================ FILE: src/openai/types/upload_complete_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Required, TypedDict from .._types import SequenceNotStr __all__ = ["UploadCompleteParams"] class UploadCompleteParams(TypedDict, total=False): part_ids: Required[SequenceNotStr[str]] """The ordered list of Part IDs.""" md5: str """ The optional md5 checksum for the file contents to verify if the bytes uploaded matches what you expect. """ ================================================ FILE: src/openai/types/upload_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict from .file_purpose import FilePurpose __all__ = ["UploadCreateParams", "ExpiresAfter"] class UploadCreateParams(TypedDict, total=False): bytes: Required[int] """The number of bytes in the file you are uploading.""" filename: Required[str] """The name of the file to upload.""" mime_type: Required[str] """The MIME type of the file. This must fall within the supported MIME types for your file purpose. See the supported MIME types for assistants and vision. """ purpose: Required[FilePurpose] """The intended purpose of the uploaded file. See the [documentation on File purposes](https://platform.openai.com/docs/api-reference/files/create#files-create-purpose). """ expires_after: ExpiresAfter """The expiration policy for a file. By default, files with `purpose=batch` expire after 30 days and all other files are persisted until they are manually deleted. """ class ExpiresAfter(TypedDict, total=False): """The expiration policy for a file. By default, files with `purpose=batch` expire after 30 days and all other files are persisted until they are manually deleted. """ anchor: Required[Literal["created_at"]] """Anchor timestamp after which the expiration policy applies. Supported anchors: `created_at`. """ seconds: Required[int] """The number of seconds after the anchor time that the file will expire. Must be between 3600 (1 hour) and 2592000 (30 days). """ ================================================ FILE: src/openai/types/uploads/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .upload_part import UploadPart as UploadPart from .part_create_params import PartCreateParams as PartCreateParams ================================================ FILE: src/openai/types/uploads/part_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Required, TypedDict from ..._types import FileTypes __all__ = ["PartCreateParams"] class PartCreateParams(TypedDict, total=False): data: Required[FileTypes] """The chunk of bytes for this Part.""" ================================================ FILE: src/openai/types/uploads/upload_part.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["UploadPart"] class UploadPart(BaseModel): """The upload Part represents a chunk of bytes we can add to an Upload object.""" id: str """The upload Part unique identifier, which can be referenced in API endpoints.""" created_at: int """The Unix timestamp (in seconds) for when the Part was created.""" object: Literal["upload.part"] """The object type, which is always `upload.part`.""" upload_id: str """The ID of the Upload object that this Part was added to.""" ================================================ FILE: src/openai/types/vector_store.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from .._models import BaseModel from .shared.metadata import Metadata __all__ = ["VectorStore", "FileCounts", "ExpiresAfter"] class FileCounts(BaseModel): cancelled: int """The number of files that were cancelled.""" completed: int """The number of files that have been successfully processed.""" failed: int """The number of files that have failed to process.""" in_progress: int """The number of files that are currently being processed.""" total: int """The total number of files.""" class ExpiresAfter(BaseModel): """The expiration policy for a vector store.""" anchor: Literal["last_active_at"] """Anchor timestamp after which the expiration policy applies. Supported anchors: `last_active_at`. """ days: int """The number of days after the anchor time that the vector store will expire.""" class VectorStore(BaseModel): """ A vector store is a collection of processed files can be used by the `file_search` tool. """ id: str """The identifier, which can be referenced in API endpoints.""" created_at: int """The Unix timestamp (in seconds) for when the vector store was created.""" file_counts: FileCounts last_active_at: Optional[int] = None """The Unix timestamp (in seconds) for when the vector store was last active.""" metadata: Optional[Metadata] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ name: str """The name of the vector store.""" object: Literal["vector_store"] """The object type, which is always `vector_store`.""" status: Literal["expired", "in_progress", "completed"] """ The status of the vector store, which can be either `expired`, `in_progress`, or `completed`. A status of `completed` indicates that the vector store is ready for use. """ usage_bytes: int """The total number of bytes used by the files in the vector store.""" expires_after: Optional[ExpiresAfter] = None """The expiration policy for a vector store.""" expires_at: Optional[int] = None """The Unix timestamp (in seconds) for when the vector store will expire.""" ================================================ FILE: src/openai/types/vector_store_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Literal, Required, TypedDict from .._types import SequenceNotStr from .shared_params.metadata import Metadata from .file_chunking_strategy_param import FileChunkingStrategyParam __all__ = ["VectorStoreCreateParams", "ExpiresAfter"] class VectorStoreCreateParams(TypedDict, total=False): chunking_strategy: FileChunkingStrategyParam """The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. Only applicable if `file_ids` is non-empty. """ description: str """A description for the vector store. Can be used to describe the vector store's purpose. """ expires_after: ExpiresAfter """The expiration policy for a vector store.""" file_ids: SequenceNotStr[str] """ A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the vector store should use. Useful for tools like `file_search` that can access files. """ metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ name: str """The name of the vector store.""" class ExpiresAfter(TypedDict, total=False): """The expiration policy for a vector store.""" anchor: Required[Literal["last_active_at"]] """Anchor timestamp after which the expiration policy applies. Supported anchors: `last_active_at`. """ days: Required[int] """The number of days after the anchor time that the vector store will expire.""" ================================================ FILE: src/openai/types/vector_store_deleted.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .._models import BaseModel __all__ = ["VectorStoreDeleted"] class VectorStoreDeleted(BaseModel): id: str deleted: bool object: Literal["vector_store.deleted"] ================================================ FILE: src/openai/types/vector_store_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["VectorStoreListParams"] class VectorStoreListParams(TypedDict, total=False): after: str """A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. """ before: str """A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. """ limit: int """A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. """ order: Literal["asc", "desc"] """Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. """ ================================================ FILE: src/openai/types/vector_store_search_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, Required, TypeAlias, TypedDict from .._types import SequenceNotStr from .shared_params.compound_filter import CompoundFilter from .shared_params.comparison_filter import ComparisonFilter __all__ = ["VectorStoreSearchParams", "Filters", "RankingOptions"] class VectorStoreSearchParams(TypedDict, total=False): query: Required[Union[str, SequenceNotStr[str]]] """A query string for a search""" filters: Filters """A filter to apply based on file attributes.""" max_num_results: int """The maximum number of results to return. This number should be between 1 and 50 inclusive. """ ranking_options: RankingOptions """Ranking options for search.""" rewrite_query: bool """Whether to rewrite the natural language query for vector search.""" Filters: TypeAlias = Union[ComparisonFilter, CompoundFilter] class RankingOptions(TypedDict, total=False): """Ranking options for search.""" ranker: Literal["none", "auto", "default-2024-11-15"] """Enable re-ranking; set to `none` to disable, which can help reduce latency.""" score_threshold: float ================================================ FILE: src/openai/types/vector_store_search_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional from typing_extensions import Literal from .._models import BaseModel __all__ = ["VectorStoreSearchResponse", "Content"] class Content(BaseModel): text: str """The text content returned from search.""" type: Literal["text"] """The type of content.""" class VectorStoreSearchResponse(BaseModel): attributes: Optional[Dict[str, Union[str, float, bool]]] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters, booleans, or numbers. """ content: List[Content] """Content chunks from the file.""" file_id: str """The ID of the vector store file.""" filename: str """The name of the vector store file.""" score: float """The similarity score for the result.""" ================================================ FILE: src/openai/types/vector_store_update_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Optional from typing_extensions import Literal, Required, TypedDict from .shared_params.metadata import Metadata __all__ = ["VectorStoreUpdateParams", "ExpiresAfter"] class VectorStoreUpdateParams(TypedDict, total=False): expires_after: Optional[ExpiresAfter] """The expiration policy for a vector store.""" metadata: Optional[Metadata] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters. """ name: Optional[str] """The name of the vector store.""" class ExpiresAfter(TypedDict, total=False): """The expiration policy for a vector store.""" anchor: Required[Literal["last_active_at"]] """Anchor timestamp after which the expiration policy applies. Supported anchors: `last_active_at`. """ days: Required[int] """The number of days after the anchor time that the vector store will expire.""" ================================================ FILE: src/openai/types/vector_stores/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .file_list_params import FileListParams as FileListParams from .vector_store_file import VectorStoreFile as VectorStoreFile from .file_create_params import FileCreateParams as FileCreateParams from .file_update_params import FileUpdateParams as FileUpdateParams from .file_content_response import FileContentResponse as FileContentResponse from .vector_store_file_batch import VectorStoreFileBatch as VectorStoreFileBatch from .file_batch_create_params import FileBatchCreateParams as FileBatchCreateParams from .vector_store_file_deleted import VectorStoreFileDeleted as VectorStoreFileDeleted from .file_batch_list_files_params import FileBatchListFilesParams as FileBatchListFilesParams ================================================ FILE: src/openai/types/vector_stores/file_batch_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Union, Iterable, Optional from typing_extensions import Required, TypedDict from ..._types import SequenceNotStr from ..file_chunking_strategy_param import FileChunkingStrategyParam __all__ = ["FileBatchCreateParams", "File"] class FileBatchCreateParams(TypedDict, total=False): attributes: Optional[Dict[str, Union[str, float, bool]]] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters, booleans, or numbers. """ chunking_strategy: FileChunkingStrategyParam """The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. Only applicable if `file_ids` is non-empty. """ file_ids: SequenceNotStr[str] """ A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the vector store should use. Useful for tools like `file_search` that can access files. If `attributes` or `chunking_strategy` are provided, they will be applied to all files in the batch. The maximum batch size is 2000 files. Mutually exclusive with `files`. """ files: Iterable[File] """ A list of objects that each include a `file_id` plus optional `attributes` or `chunking_strategy`. Use this when you need to override metadata for specific files. The global `attributes` or `chunking_strategy` will be ignored and must be specified for each file. The maximum batch size is 2000 files. Mutually exclusive with `file_ids`. """ class File(TypedDict, total=False): file_id: Required[str] """ A [File](https://platform.openai.com/docs/api-reference/files) ID that the vector store should use. Useful for tools like `file_search` that can access files. """ attributes: Optional[Dict[str, Union[str, float, bool]]] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters, booleans, or numbers. """ chunking_strategy: FileChunkingStrategyParam """The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. Only applicable if `file_ids` is non-empty. """ ================================================ FILE: src/openai/types/vector_stores/file_batch_list_files_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, Required, TypedDict __all__ = ["FileBatchListFilesParams"] class FileBatchListFilesParams(TypedDict, total=False): vector_store_id: Required[str] after: str """A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. """ before: str """A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. """ filter: Literal["in_progress", "completed", "failed", "cancelled"] """Filter by file status. One of `in_progress`, `completed`, `failed`, `cancelled`. """ limit: int """A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. """ order: Literal["asc", "desc"] """Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. """ ================================================ FILE: src/openai/types/vector_stores/file_content_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from ..._models import BaseModel __all__ = ["FileContentResponse"] class FileContentResponse(BaseModel): text: Optional[str] = None """The text content""" type: Optional[str] = None """The content type (currently only `"text"`)""" ================================================ FILE: src/openai/types/vector_stores/file_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Union, Optional from typing_extensions import Required, TypedDict from ..file_chunking_strategy_param import FileChunkingStrategyParam __all__ = ["FileCreateParams"] class FileCreateParams(TypedDict, total=False): file_id: Required[str] """ A [File](https://platform.openai.com/docs/api-reference/files) ID that the vector store should use. Useful for tools like `file_search` that can access files. """ attributes: Optional[Dict[str, Union[str, float, bool]]] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters, booleans, or numbers. """ chunking_strategy: FileChunkingStrategyParam """The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. Only applicable if `file_ids` is non-empty. """ ================================================ FILE: src/openai/types/vector_stores/file_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["FileListParams"] class FileListParams(TypedDict, total=False): after: str """A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. """ before: str """A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. """ filter: Literal["in_progress", "completed", "failed", "cancelled"] """Filter by file status. One of `in_progress`, `completed`, `failed`, `cancelled`. """ limit: int """A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. """ order: Literal["asc", "desc"] """Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. """ ================================================ FILE: src/openai/types/vector_stores/file_update_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Dict, Union, Optional from typing_extensions import Required, TypedDict __all__ = ["FileUpdateParams"] class FileUpdateParams(TypedDict, total=False): vector_store_id: Required[str] attributes: Required[Optional[Dict[str, Union[str, float, bool]]]] """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters, booleans, or numbers. """ ================================================ FILE: src/openai/types/vector_stores/vector_store_file.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, Union, Optional from typing_extensions import Literal from ..._models import BaseModel from ..file_chunking_strategy import FileChunkingStrategy __all__ = ["VectorStoreFile", "LastError"] class LastError(BaseModel): """The last error associated with this vector store file. Will be `null` if there are no errors. """ code: Literal["server_error", "unsupported_file", "invalid_file"] """One of `server_error`, `unsupported_file`, or `invalid_file`.""" message: str """A human-readable description of the error.""" class VectorStoreFile(BaseModel): """A list of files attached to a vector store.""" id: str """The identifier, which can be referenced in API endpoints.""" created_at: int """The Unix timestamp (in seconds) for when the vector store file was created.""" last_error: Optional[LastError] = None """The last error associated with this vector store file. Will be `null` if there are no errors. """ object: Literal["vector_store.file"] """The object type, which is always `vector_store.file`.""" status: Literal["in_progress", "completed", "cancelled", "failed"] """ The status of the vector store file, which can be either `in_progress`, `completed`, `cancelled`, or `failed`. The status `completed` indicates that the vector store file is ready for use. """ usage_bytes: int """The total vector store usage in bytes. Note that this may be different from the original file size. """ vector_store_id: str """ The ID of the [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) that the [File](https://platform.openai.com/docs/api-reference/files) is attached to. """ attributes: Optional[Dict[str, Union[str, float, bool]]] = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard. Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters, booleans, or numbers. """ chunking_strategy: Optional[FileChunkingStrategy] = None """The strategy used to chunk the file.""" ================================================ FILE: src/openai/types/vector_stores/vector_store_file_batch.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["VectorStoreFileBatch", "FileCounts"] class FileCounts(BaseModel): cancelled: int """The number of files that where cancelled.""" completed: int """The number of files that have been processed.""" failed: int """The number of files that have failed to process.""" in_progress: int """The number of files that are currently being processed.""" total: int """The total number of files.""" class VectorStoreFileBatch(BaseModel): """A batch of files attached to a vector store.""" id: str """The identifier, which can be referenced in API endpoints.""" created_at: int """ The Unix timestamp (in seconds) for when the vector store files batch was created. """ file_counts: FileCounts object: Literal["vector_store.files_batch"] """The object type, which is always `vector_store.file_batch`.""" status: Literal["in_progress", "completed", "cancelled", "failed"] """ The status of the vector store files batch, which can be either `in_progress`, `completed`, `cancelled` or `failed`. """ vector_store_id: str """ The ID of the [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) that the [File](https://platform.openai.com/docs/api-reference/files) is attached to. """ ================================================ FILE: src/openai/types/vector_stores/vector_store_file_deleted.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from ..._models import BaseModel __all__ = ["VectorStoreFileDeleted"] class VectorStoreFileDeleted(BaseModel): id: str deleted: bool object: Literal["vector_store.file.deleted"] ================================================ FILE: src/openai/types/video.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional from typing_extensions import Literal from .._models import BaseModel from .video_size import VideoSize from .video_model import VideoModel from .video_seconds import VideoSeconds from .video_create_error import VideoCreateError __all__ = ["Video"] class Video(BaseModel): """Structured information describing a generated video job.""" id: str """Unique identifier for the video job.""" completed_at: Optional[int] = None """Unix timestamp (seconds) for when the job completed, if finished.""" created_at: int """Unix timestamp (seconds) for when the job was created.""" error: Optional[VideoCreateError] = None """Error payload that explains why generation failed, if applicable.""" expires_at: Optional[int] = None """Unix timestamp (seconds) for when the downloadable assets expire, if set.""" model: VideoModel """The video generation model that produced the job.""" object: Literal["video"] """The object type, which is always `video`.""" progress: int """Approximate completion percentage for the generation task.""" prompt: Optional[str] = None """The prompt that was used to generate the video.""" remixed_from_video_id: Optional[str] = None """Identifier of the source video if this video is a remix.""" seconds: Union[str, VideoSeconds] """Duration of the generated clip in seconds. For extensions, this is the stitched total duration. """ size: VideoSize """The resolution of the generated video.""" status: Literal["queued", "in_progress", "completed", "failed"] """Current lifecycle status of the video job.""" ================================================ FILE: src/openai/types/video_create_character_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Required, TypedDict from .._types import FileTypes __all__ = ["VideoCreateCharacterParams"] class VideoCreateCharacterParams(TypedDict, total=False): name: Required[str] """Display name for this API character.""" video: Required[FileTypes] """Video file used to create a character.""" ================================================ FILE: src/openai/types/video_create_character_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from .._models import BaseModel __all__ = ["VideoCreateCharacterResponse"] class VideoCreateCharacterResponse(BaseModel): id: Optional[str] = None """Identifier for the character creation cameo.""" created_at: int """Unix timestamp (in seconds) when the character was created.""" name: Optional[str] = None """Display name for the character.""" ================================================ FILE: src/openai/types/video_create_error.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .._models import BaseModel __all__ = ["VideoCreateError"] class VideoCreateError(BaseModel): """An error that occurred while generating the response.""" code: str """A machine-readable error code that was returned.""" message: str """A human-readable description of the error that was returned.""" ================================================ FILE: src/openai/types/video_create_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Required, TypeAlias, TypedDict from .._types import FileTypes from .video_size import VideoSize from .video_seconds import VideoSeconds from .video_model_param import VideoModelParam from .image_input_reference_param import ImageInputReferenceParam __all__ = ["VideoCreateParams", "InputReference"] class VideoCreateParams(TypedDict, total=False): prompt: Required[str] """Text prompt that describes the video to generate.""" input_reference: InputReference """Optional reference asset upload or reference object that guides generation.""" model: VideoModelParam """The video generation model to use (allowed values: sora-2, sora-2-pro). Defaults to `sora-2`. """ seconds: VideoSeconds """Clip duration in seconds (allowed values: 4, 8, 12). Defaults to 4 seconds.""" size: VideoSize """ Output resolution formatted as width x height (allowed values: 720x1280, 1280x720, 1024x1792, 1792x1024). Defaults to 720x1280. """ InputReference: TypeAlias = Union[FileTypes, ImageInputReferenceParam] ================================================ FILE: src/openai/types/video_delete_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal from .._models import BaseModel __all__ = ["VideoDeleteResponse"] class VideoDeleteResponse(BaseModel): """Confirmation payload returned after deleting a video.""" id: str """Identifier of the deleted video.""" deleted: bool """Indicates that the video resource was deleted.""" object: Literal["video.deleted"] """The object type that signals the deletion response.""" ================================================ FILE: src/openai/types/video_download_content_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["VideoDownloadContentParams"] class VideoDownloadContentParams(TypedDict, total=False): variant: Literal["video", "thumbnail", "spritesheet"] """Which downloadable asset to return. Defaults to the MP4 video.""" ================================================ FILE: src/openai/types/video_edit_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Required, TypeAlias, TypedDict from .._types import FileTypes __all__ = ["VideoEditParams", "Video", "VideoVideoReferenceInputParam"] class VideoEditParams(TypedDict, total=False): prompt: Required[str] """Text prompt that describes how to edit the source video.""" video: Required[Video] """Reference to the completed video to edit.""" class VideoVideoReferenceInputParam(TypedDict, total=False): """Reference to the completed video.""" id: Required[str] """The identifier of the completed video.""" Video: TypeAlias = Union[FileTypes, VideoVideoReferenceInputParam] ================================================ FILE: src/openai/types/video_extend_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Required, TypeAlias, TypedDict from .._types import FileTypes from .video_seconds import VideoSeconds __all__ = ["VideoExtendParams", "Video", "VideoVideoReferenceInputParam"] class VideoExtendParams(TypedDict, total=False): prompt: Required[str] """Updated text prompt that directs the extension generation.""" seconds: Required[VideoSeconds] """ Length of the newly generated extension segment in seconds (allowed values: 4, 8, 12, 16, 20). """ video: Required[Video] """Reference to the completed video to extend.""" class VideoVideoReferenceInputParam(TypedDict, total=False): """Reference to the completed video.""" id: Required[str] """The identifier of the completed video.""" Video: TypeAlias = Union[FileTypes, VideoVideoReferenceInputParam] ================================================ FILE: src/openai/types/video_get_character_response.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from .._models import BaseModel __all__ = ["VideoGetCharacterResponse"] class VideoGetCharacterResponse(BaseModel): id: Optional[str] = None """Identifier for the character creation cameo.""" created_at: int """Unix timestamp (in seconds) when the character was created.""" name: Optional[str] = None """Display name for the character.""" ================================================ FILE: src/openai/types/video_list_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Literal, TypedDict __all__ = ["VideoListParams"] class VideoListParams(TypedDict, total=False): after: str """Identifier for the last item from the previous pagination request""" limit: int """Number of items to retrieve""" order: Literal["asc", "desc"] """Sort order of results by timestamp. Use `asc` for ascending order or `desc` for descending order. """ ================================================ FILE: src/openai/types/video_model.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Literal, TypeAlias __all__ = ["VideoModel"] VideoModel: TypeAlias = Union[ str, Literal["sora-2", "sora-2-pro", "sora-2-2025-10-06", "sora-2-pro-2025-10-06", "sora-2-2025-12-08"] ] ================================================ FILE: src/openai/types/video_model_param.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Union from typing_extensions import Literal, TypeAlias __all__ = ["VideoModelParam"] VideoModelParam: TypeAlias = Union[ str, Literal["sora-2", "sora-2-pro", "sora-2-2025-10-06", "sora-2-pro-2025-10-06", "sora-2-2025-12-08"] ] ================================================ FILE: src/openai/types/video_remix_params.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing_extensions import Required, TypedDict __all__ = ["VideoRemixParams"] class VideoRemixParams(TypedDict, total=False): prompt: Required[str] """Updated text prompt that directs the remix generation.""" ================================================ FILE: src/openai/types/video_seconds.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["VideoSeconds"] VideoSeconds: TypeAlias = Literal["4", "8", "12"] ================================================ FILE: src/openai/types/video_size.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing_extensions import Literal, TypeAlias __all__ = ["VideoSize"] VideoSize: TypeAlias = Literal["720x1280", "1280x720", "1024x1792", "1792x1024"] ================================================ FILE: src/openai/types/webhooks/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from .unwrap_webhook_event import UnwrapWebhookEvent as UnwrapWebhookEvent from .batch_failed_webhook_event import BatchFailedWebhookEvent as BatchFailedWebhookEvent from .batch_expired_webhook_event import BatchExpiredWebhookEvent as BatchExpiredWebhookEvent from .batch_cancelled_webhook_event import BatchCancelledWebhookEvent as BatchCancelledWebhookEvent from .batch_completed_webhook_event import BatchCompletedWebhookEvent as BatchCompletedWebhookEvent from .eval_run_failed_webhook_event import EvalRunFailedWebhookEvent as EvalRunFailedWebhookEvent from .response_failed_webhook_event import ResponseFailedWebhookEvent as ResponseFailedWebhookEvent from .eval_run_canceled_webhook_event import EvalRunCanceledWebhookEvent as EvalRunCanceledWebhookEvent from .eval_run_succeeded_webhook_event import EvalRunSucceededWebhookEvent as EvalRunSucceededWebhookEvent from .response_cancelled_webhook_event import ResponseCancelledWebhookEvent as ResponseCancelledWebhookEvent from .response_completed_webhook_event import ResponseCompletedWebhookEvent as ResponseCompletedWebhookEvent from .response_incomplete_webhook_event import ResponseIncompleteWebhookEvent as ResponseIncompleteWebhookEvent from .fine_tuning_job_failed_webhook_event import FineTuningJobFailedWebhookEvent as FineTuningJobFailedWebhookEvent from .realtime_call_incoming_webhook_event import RealtimeCallIncomingWebhookEvent as RealtimeCallIncomingWebhookEvent from .fine_tuning_job_cancelled_webhook_event import ( FineTuningJobCancelledWebhookEvent as FineTuningJobCancelledWebhookEvent, ) from .fine_tuning_job_succeeded_webhook_event import ( FineTuningJobSucceededWebhookEvent as FineTuningJobSucceededWebhookEvent, ) ================================================ FILE: src/openai/types/webhooks/batch_cancelled_webhook_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["BatchCancelledWebhookEvent", "Data"] class Data(BaseModel): """Event data payload.""" id: str """The unique ID of the batch API request.""" class BatchCancelledWebhookEvent(BaseModel): """Sent when a batch API request has been cancelled.""" id: str """The unique ID of the event.""" created_at: int """The Unix timestamp (in seconds) of when the batch API request was cancelled.""" data: Data """Event data payload.""" type: Literal["batch.cancelled"] """The type of the event. Always `batch.cancelled`.""" object: Optional[Literal["event"]] = None """The object of the event. Always `event`.""" ================================================ FILE: src/openai/types/webhooks/batch_completed_webhook_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["BatchCompletedWebhookEvent", "Data"] class Data(BaseModel): """Event data payload.""" id: str """The unique ID of the batch API request.""" class BatchCompletedWebhookEvent(BaseModel): """Sent when a batch API request has been completed.""" id: str """The unique ID of the event.""" created_at: int """The Unix timestamp (in seconds) of when the batch API request was completed.""" data: Data """Event data payload.""" type: Literal["batch.completed"] """The type of the event. Always `batch.completed`.""" object: Optional[Literal["event"]] = None """The object of the event. Always `event`.""" ================================================ FILE: src/openai/types/webhooks/batch_expired_webhook_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["BatchExpiredWebhookEvent", "Data"] class Data(BaseModel): """Event data payload.""" id: str """The unique ID of the batch API request.""" class BatchExpiredWebhookEvent(BaseModel): """Sent when a batch API request has expired.""" id: str """The unique ID of the event.""" created_at: int """The Unix timestamp (in seconds) of when the batch API request expired.""" data: Data """Event data payload.""" type: Literal["batch.expired"] """The type of the event. Always `batch.expired`.""" object: Optional[Literal["event"]] = None """The object of the event. Always `event`.""" ================================================ FILE: src/openai/types/webhooks/batch_failed_webhook_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["BatchFailedWebhookEvent", "Data"] class Data(BaseModel): """Event data payload.""" id: str """The unique ID of the batch API request.""" class BatchFailedWebhookEvent(BaseModel): """Sent when a batch API request has failed.""" id: str """The unique ID of the event.""" created_at: int """The Unix timestamp (in seconds) of when the batch API request failed.""" data: Data """Event data payload.""" type: Literal["batch.failed"] """The type of the event. Always `batch.failed`.""" object: Optional[Literal["event"]] = None """The object of the event. Always `event`.""" ================================================ FILE: src/openai/types/webhooks/eval_run_canceled_webhook_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["EvalRunCanceledWebhookEvent", "Data"] class Data(BaseModel): """Event data payload.""" id: str """The unique ID of the eval run.""" class EvalRunCanceledWebhookEvent(BaseModel): """Sent when an eval run has been canceled.""" id: str """The unique ID of the event.""" created_at: int """The Unix timestamp (in seconds) of when the eval run was canceled.""" data: Data """Event data payload.""" type: Literal["eval.run.canceled"] """The type of the event. Always `eval.run.canceled`.""" object: Optional[Literal["event"]] = None """The object of the event. Always `event`.""" ================================================ FILE: src/openai/types/webhooks/eval_run_failed_webhook_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["EvalRunFailedWebhookEvent", "Data"] class Data(BaseModel): """Event data payload.""" id: str """The unique ID of the eval run.""" class EvalRunFailedWebhookEvent(BaseModel): """Sent when an eval run has failed.""" id: str """The unique ID of the event.""" created_at: int """The Unix timestamp (in seconds) of when the eval run failed.""" data: Data """Event data payload.""" type: Literal["eval.run.failed"] """The type of the event. Always `eval.run.failed`.""" object: Optional[Literal["event"]] = None """The object of the event. Always `event`.""" ================================================ FILE: src/openai/types/webhooks/eval_run_succeeded_webhook_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["EvalRunSucceededWebhookEvent", "Data"] class Data(BaseModel): """Event data payload.""" id: str """The unique ID of the eval run.""" class EvalRunSucceededWebhookEvent(BaseModel): """Sent when an eval run has succeeded.""" id: str """The unique ID of the event.""" created_at: int """The Unix timestamp (in seconds) of when the eval run succeeded.""" data: Data """Event data payload.""" type: Literal["eval.run.succeeded"] """The type of the event. Always `eval.run.succeeded`.""" object: Optional[Literal["event"]] = None """The object of the event. Always `event`.""" ================================================ FILE: src/openai/types/webhooks/fine_tuning_job_cancelled_webhook_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["FineTuningJobCancelledWebhookEvent", "Data"] class Data(BaseModel): """Event data payload.""" id: str """The unique ID of the fine-tuning job.""" class FineTuningJobCancelledWebhookEvent(BaseModel): """Sent when a fine-tuning job has been cancelled.""" id: str """The unique ID of the event.""" created_at: int """The Unix timestamp (in seconds) of when the fine-tuning job was cancelled.""" data: Data """Event data payload.""" type: Literal["fine_tuning.job.cancelled"] """The type of the event. Always `fine_tuning.job.cancelled`.""" object: Optional[Literal["event"]] = None """The object of the event. Always `event`.""" ================================================ FILE: src/openai/types/webhooks/fine_tuning_job_failed_webhook_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["FineTuningJobFailedWebhookEvent", "Data"] class Data(BaseModel): """Event data payload.""" id: str """The unique ID of the fine-tuning job.""" class FineTuningJobFailedWebhookEvent(BaseModel): """Sent when a fine-tuning job has failed.""" id: str """The unique ID of the event.""" created_at: int """The Unix timestamp (in seconds) of when the fine-tuning job failed.""" data: Data """Event data payload.""" type: Literal["fine_tuning.job.failed"] """The type of the event. Always `fine_tuning.job.failed`.""" object: Optional[Literal["event"]] = None """The object of the event. Always `event`.""" ================================================ FILE: src/openai/types/webhooks/fine_tuning_job_succeeded_webhook_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["FineTuningJobSucceededWebhookEvent", "Data"] class Data(BaseModel): """Event data payload.""" id: str """The unique ID of the fine-tuning job.""" class FineTuningJobSucceededWebhookEvent(BaseModel): """Sent when a fine-tuning job has succeeded.""" id: str """The unique ID of the event.""" created_at: int """The Unix timestamp (in seconds) of when the fine-tuning job succeeded.""" data: Data """Event data payload.""" type: Literal["fine_tuning.job.succeeded"] """The type of the event. Always `fine_tuning.job.succeeded`.""" object: Optional[Literal["event"]] = None """The object of the event. Always `event`.""" ================================================ FILE: src/openai/types/webhooks/realtime_call_incoming_webhook_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["RealtimeCallIncomingWebhookEvent", "Data", "DataSipHeader"] class DataSipHeader(BaseModel): """A header from the SIP Invite.""" name: str """Name of the SIP Header.""" value: str """Value of the SIP Header.""" class Data(BaseModel): """Event data payload.""" call_id: str """The unique ID of this call.""" sip_headers: List[DataSipHeader] """Headers from the SIP Invite.""" class RealtimeCallIncomingWebhookEvent(BaseModel): """Sent when Realtime API Receives a incoming SIP call.""" id: str """The unique ID of the event.""" created_at: int """The Unix timestamp (in seconds) of when the model response was completed.""" data: Data """Event data payload.""" type: Literal["realtime.call.incoming"] """The type of the event. Always `realtime.call.incoming`.""" object: Optional[Literal["event"]] = None """The object of the event. Always `event`.""" ================================================ FILE: src/openai/types/webhooks/response_cancelled_webhook_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseCancelledWebhookEvent", "Data"] class Data(BaseModel): """Event data payload.""" id: str """The unique ID of the model response.""" class ResponseCancelledWebhookEvent(BaseModel): """Sent when a background response has been cancelled.""" id: str """The unique ID of the event.""" created_at: int """The Unix timestamp (in seconds) of when the model response was cancelled.""" data: Data """Event data payload.""" type: Literal["response.cancelled"] """The type of the event. Always `response.cancelled`.""" object: Optional[Literal["event"]] = None """The object of the event. Always `event`.""" ================================================ FILE: src/openai/types/webhooks/response_completed_webhook_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseCompletedWebhookEvent", "Data"] class Data(BaseModel): """Event data payload.""" id: str """The unique ID of the model response.""" class ResponseCompletedWebhookEvent(BaseModel): """Sent when a background response has been completed.""" id: str """The unique ID of the event.""" created_at: int """The Unix timestamp (in seconds) of when the model response was completed.""" data: Data """Event data payload.""" type: Literal["response.completed"] """The type of the event. Always `response.completed`.""" object: Optional[Literal["event"]] = None """The object of the event. Always `event`.""" ================================================ FILE: src/openai/types/webhooks/response_failed_webhook_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseFailedWebhookEvent", "Data"] class Data(BaseModel): """Event data payload.""" id: str """The unique ID of the model response.""" class ResponseFailedWebhookEvent(BaseModel): """Sent when a background response has failed.""" id: str """The unique ID of the event.""" created_at: int """The Unix timestamp (in seconds) of when the model response failed.""" data: Data """Event data payload.""" type: Literal["response.failed"] """The type of the event. Always `response.failed`.""" object: Optional[Literal["event"]] = None """The object of the event. Always `event`.""" ================================================ FILE: src/openai/types/webhooks/response_incomplete_webhook_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional from typing_extensions import Literal from ..._models import BaseModel __all__ = ["ResponseIncompleteWebhookEvent", "Data"] class Data(BaseModel): """Event data payload.""" id: str """The unique ID of the model response.""" class ResponseIncompleteWebhookEvent(BaseModel): """Sent when a background response has been interrupted.""" id: str """The unique ID of the event.""" created_at: int """The Unix timestamp (in seconds) of when the model response was interrupted.""" data: Data """Event data payload.""" type: Literal["response.incomplete"] """The type of the event. Always `response.incomplete`.""" object: Optional[Literal["event"]] = None """The object of the event. Always `event`.""" ================================================ FILE: src/openai/types/webhooks/unwrap_webhook_event.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union from typing_extensions import Annotated, TypeAlias from ..._utils import PropertyInfo from .batch_failed_webhook_event import BatchFailedWebhookEvent from .batch_expired_webhook_event import BatchExpiredWebhookEvent from .batch_cancelled_webhook_event import BatchCancelledWebhookEvent from .batch_completed_webhook_event import BatchCompletedWebhookEvent from .eval_run_failed_webhook_event import EvalRunFailedWebhookEvent from .response_failed_webhook_event import ResponseFailedWebhookEvent from .eval_run_canceled_webhook_event import EvalRunCanceledWebhookEvent from .eval_run_succeeded_webhook_event import EvalRunSucceededWebhookEvent from .response_cancelled_webhook_event import ResponseCancelledWebhookEvent from .response_completed_webhook_event import ResponseCompletedWebhookEvent from .response_incomplete_webhook_event import ResponseIncompleteWebhookEvent from .fine_tuning_job_failed_webhook_event import FineTuningJobFailedWebhookEvent from .realtime_call_incoming_webhook_event import RealtimeCallIncomingWebhookEvent from .fine_tuning_job_cancelled_webhook_event import FineTuningJobCancelledWebhookEvent from .fine_tuning_job_succeeded_webhook_event import FineTuningJobSucceededWebhookEvent __all__ = ["UnwrapWebhookEvent"] UnwrapWebhookEvent: TypeAlias = Annotated[ Union[ BatchCancelledWebhookEvent, BatchCompletedWebhookEvent, BatchExpiredWebhookEvent, BatchFailedWebhookEvent, EvalRunCanceledWebhookEvent, EvalRunFailedWebhookEvent, EvalRunSucceededWebhookEvent, FineTuningJobCancelledWebhookEvent, FineTuningJobFailedWebhookEvent, FineTuningJobSucceededWebhookEvent, RealtimeCallIncomingWebhookEvent, ResponseCancelledWebhookEvent, ResponseCompletedWebhookEvent, ResponseFailedWebhookEvent, ResponseIncompleteWebhookEvent, ], PropertyInfo(discriminator="type"), ] ================================================ FILE: src/openai/types/websocket_connection_options.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import TYPE_CHECKING from typing_extensions import Sequence, TypeAlias, TypedDict __all__ = ["WebSocketConnectionOptions", "WebsocketConnectionOptions"] if TYPE_CHECKING: from websockets import Subprotocol from websockets.extensions import ClientExtensionFactory class WebSocketConnectionOptions(TypedDict, total=False): """WebSocket connection options copied from `websockets`. For example: https://websockets.readthedocs.io/en/stable/reference/asyncio/client.html#websockets.asyncio.client.connect """ extensions: Sequence[ClientExtensionFactory] | None """List of supported extensions, in order in which they should be negotiated and run.""" subprotocols: Sequence[Subprotocol] | None """List of supported subprotocols, in order of decreasing preference.""" compression: str | None """The “permessage-deflate” extension is enabled by default. Set compression to None to disable it. See the [compression guide](https://websockets.readthedocs.io/en/stable/topics/compression.html) for details.""" # limits max_size: int | None """Maximum size of incoming messages in bytes. None disables the limit.""" max_queue: int | None | tuple[int | None, int | None] """High-water mark of the buffer where frames are received. It defaults to 16 frames. The low-water mark defaults to max_queue // 4. You may pass a (high, low) tuple to set the high-water and low-water marks. If you want to disable flow control entirely, you may set it to None, although that’s a bad idea.""" write_limit: int | tuple[int, int | None] """High-water mark of write buffer in bytes. It is passed to set_write_buffer_limits(). It defaults to 32 KiB. You may pass a (high, low) tuple to set the high-water and low-water marks.""" # Backward compatibility for pre-rename imports. WebsocketConnectionOptions: TypeAlias = WebSocketConnectionOptions ================================================ FILE: src/openai/version.py ================================================ from ._version import __version__ VERSION: str = __version__ ================================================ FILE: tests/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/audio/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/audio/test_speech.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import httpx import pytest from respx import MockRouter import openai._legacy_response as _legacy_response from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type # pyright: reportDeprecated=false base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestSpeech: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize @pytest.mark.respx(base_url=base_url) def test_method_create(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.post("/audio/speech").mock(return_value=httpx.Response(200, json={"foo": "bar"})) speech = client.audio.speech.create( input="string", model="string", voice="string", ) assert isinstance(speech, _legacy_response.HttpxBinaryResponseContent) assert speech.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) def test_method_create_with_all_params(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.post("/audio/speech").mock(return_value=httpx.Response(200, json={"foo": "bar"})) speech = client.audio.speech.create( input="string", model="string", voice="string", instructions="instructions", response_format="mp3", speed=0.25, stream_format="sse", ) assert isinstance(speech, _legacy_response.HttpxBinaryResponseContent) assert speech.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) def test_raw_response_create(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.post("/audio/speech").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = client.audio.speech.with_raw_response.create( input="string", model="string", voice="string", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" speech = response.parse() assert_matches_type(_legacy_response.HttpxBinaryResponseContent, speech, path=["response"]) @parametrize @pytest.mark.respx(base_url=base_url) def test_streaming_response_create(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.post("/audio/speech").mock(return_value=httpx.Response(200, json={"foo": "bar"})) with client.audio.speech.with_streaming_response.create( input="string", model="string", voice="string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" speech = response.parse() assert_matches_type(bytes, speech, path=["response"]) assert cast(Any, response.is_closed) is True class TestAsyncSpeech: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize @pytest.mark.respx(base_url=base_url) async def test_method_create(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.post("/audio/speech").mock(return_value=httpx.Response(200, json={"foo": "bar"})) speech = await async_client.audio.speech.create( input="string", model="string", voice="string", ) assert isinstance(speech, _legacy_response.HttpxBinaryResponseContent) assert speech.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) async def test_method_create_with_all_params(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.post("/audio/speech").mock(return_value=httpx.Response(200, json={"foo": "bar"})) speech = await async_client.audio.speech.create( input="string", model="string", voice="string", instructions="instructions", response_format="mp3", speed=0.25, stream_format="sse", ) assert isinstance(speech, _legacy_response.HttpxBinaryResponseContent) assert speech.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) async def test_raw_response_create(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.post("/audio/speech").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = await async_client.audio.speech.with_raw_response.create( input="string", model="string", voice="string", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" speech = response.parse() assert_matches_type(_legacy_response.HttpxBinaryResponseContent, speech, path=["response"]) @parametrize @pytest.mark.respx(base_url=base_url) async def test_streaming_response_create(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.post("/audio/speech").mock(return_value=httpx.Response(200, json={"foo": "bar"})) async with async_client.audio.speech.with_streaming_response.create( input="string", model="string", voice="string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" speech = await response.parse() assert_matches_type(bytes, speech, path=["response"]) assert cast(Any, response.is_closed) is True ================================================ FILE: tests/api_resources/audio/test_transcriptions.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types.audio import TranscriptionCreateResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestTranscriptions: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create_overload_1(self, client: OpenAI) -> None: transcription = client.audio.transcriptions.create( file=b"Example data", model="gpt-4o-transcribe", ) assert_matches_type(TranscriptionCreateResponse, transcription, path=["response"]) @parametrize def test_method_create_with_all_params_overload_1(self, client: OpenAI) -> None: transcription = client.audio.transcriptions.create( file=b"Example data", model="gpt-4o-transcribe", chunking_strategy="auto", include=["logprobs"], known_speaker_names=["string"], known_speaker_references=["string"], language="language", prompt="prompt", response_format="json", stream=False, temperature=0, timestamp_granularities=["word"], ) assert_matches_type(TranscriptionCreateResponse, transcription, path=["response"]) @parametrize def test_raw_response_create_overload_1(self, client: OpenAI) -> None: response = client.audio.transcriptions.with_raw_response.create( file=b"Example data", model="gpt-4o-transcribe", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" transcription = response.parse() assert_matches_type(TranscriptionCreateResponse, transcription, path=["response"]) @parametrize def test_streaming_response_create_overload_1(self, client: OpenAI) -> None: with client.audio.transcriptions.with_streaming_response.create( file=b"Example data", model="gpt-4o-transcribe", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" transcription = response.parse() assert_matches_type(TranscriptionCreateResponse, transcription, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_create_overload_2(self, client: OpenAI) -> None: transcription_stream = client.audio.transcriptions.create( file=b"Example data", model="gpt-4o-transcribe", stream=True, ) transcription_stream.response.close() @parametrize def test_method_create_with_all_params_overload_2(self, client: OpenAI) -> None: transcription_stream = client.audio.transcriptions.create( file=b"Example data", model="gpt-4o-transcribe", stream=True, chunking_strategy="auto", include=["logprobs"], known_speaker_names=["string"], known_speaker_references=["string"], language="language", prompt="prompt", response_format="json", temperature=0, timestamp_granularities=["word"], ) transcription_stream.response.close() @parametrize def test_raw_response_create_overload_2(self, client: OpenAI) -> None: response = client.audio.transcriptions.with_raw_response.create( file=b"Example data", model="gpt-4o-transcribe", stream=True, ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() @parametrize def test_streaming_response_create_overload_2(self, client: OpenAI) -> None: with client.audio.transcriptions.with_streaming_response.create( file=b"Example data", model="gpt-4o-transcribe", stream=True, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() assert cast(Any, response.is_closed) is True class TestAsyncTranscriptions: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create_overload_1(self, async_client: AsyncOpenAI) -> None: transcription = await async_client.audio.transcriptions.create( file=b"Example data", model="gpt-4o-transcribe", ) assert_matches_type(TranscriptionCreateResponse, transcription, path=["response"]) @parametrize async def test_method_create_with_all_params_overload_1(self, async_client: AsyncOpenAI) -> None: transcription = await async_client.audio.transcriptions.create( file=b"Example data", model="gpt-4o-transcribe", chunking_strategy="auto", include=["logprobs"], known_speaker_names=["string"], known_speaker_references=["string"], language="language", prompt="prompt", response_format="json", stream=False, temperature=0, timestamp_granularities=["word"], ) assert_matches_type(TranscriptionCreateResponse, transcription, path=["response"]) @parametrize async def test_raw_response_create_overload_1(self, async_client: AsyncOpenAI) -> None: response = await async_client.audio.transcriptions.with_raw_response.create( file=b"Example data", model="gpt-4o-transcribe", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" transcription = response.parse() assert_matches_type(TranscriptionCreateResponse, transcription, path=["response"]) @parametrize async def test_streaming_response_create_overload_1(self, async_client: AsyncOpenAI) -> None: async with async_client.audio.transcriptions.with_streaming_response.create( file=b"Example data", model="gpt-4o-transcribe", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" transcription = await response.parse() assert_matches_type(TranscriptionCreateResponse, transcription, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_create_overload_2(self, async_client: AsyncOpenAI) -> None: transcription_stream = await async_client.audio.transcriptions.create( file=b"Example data", model="gpt-4o-transcribe", stream=True, ) await transcription_stream.response.aclose() @parametrize async def test_method_create_with_all_params_overload_2(self, async_client: AsyncOpenAI) -> None: transcription_stream = await async_client.audio.transcriptions.create( file=b"Example data", model="gpt-4o-transcribe", stream=True, chunking_strategy="auto", include=["logprobs"], known_speaker_names=["string"], known_speaker_references=["string"], language="language", prompt="prompt", response_format="json", temperature=0, timestamp_granularities=["word"], ) await transcription_stream.response.aclose() @parametrize async def test_raw_response_create_overload_2(self, async_client: AsyncOpenAI) -> None: response = await async_client.audio.transcriptions.with_raw_response.create( file=b"Example data", model="gpt-4o-transcribe", stream=True, ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() await stream.close() @parametrize async def test_streaming_response_create_overload_2(self, async_client: AsyncOpenAI) -> None: async with async_client.audio.transcriptions.with_streaming_response.create( file=b"Example data", model="gpt-4o-transcribe", stream=True, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = await response.parse() await stream.close() assert cast(Any, response.is_closed) is True ================================================ FILE: tests/api_resources/audio/test_translations.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types.audio import TranslationCreateResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestTranslations: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: translation = client.audio.translations.create( file=b"Example data", model="whisper-1", ) assert_matches_type(TranslationCreateResponse, translation, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: translation = client.audio.translations.create( file=b"Example data", model="whisper-1", prompt="prompt", response_format="json", temperature=0, ) assert_matches_type(TranslationCreateResponse, translation, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.audio.translations.with_raw_response.create( file=b"Example data", model="whisper-1", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" translation = response.parse() assert_matches_type(TranslationCreateResponse, translation, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.audio.translations.with_streaming_response.create( file=b"Example data", model="whisper-1", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" translation = response.parse() assert_matches_type(TranslationCreateResponse, translation, path=["response"]) assert cast(Any, response.is_closed) is True class TestAsyncTranslations: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: translation = await async_client.audio.translations.create( file=b"Example data", model="whisper-1", ) assert_matches_type(TranslationCreateResponse, translation, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: translation = await async_client.audio.translations.create( file=b"Example data", model="whisper-1", prompt="prompt", response_format="json", temperature=0, ) assert_matches_type(TranslationCreateResponse, translation, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.audio.translations.with_raw_response.create( file=b"Example data", model="whisper-1", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" translation = response.parse() assert_matches_type(TranslationCreateResponse, translation, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.audio.translations.with_streaming_response.create( file=b"Example data", model="whisper-1", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" translation = await response.parse() assert_matches_type(TranslationCreateResponse, translation, path=["response"]) assert cast(Any, response.is_closed) is True ================================================ FILE: tests/api_resources/beta/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/beta/chatkit/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/beta/chatkit/test_sessions.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types.beta.chatkit import ( ChatSession, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestSessions: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: session = client.beta.chatkit.sessions.create( user="x", workflow={"id": "id"}, ) assert_matches_type(ChatSession, session, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: session = client.beta.chatkit.sessions.create( user="x", workflow={ "id": "id", "state_variables": {"foo": "string"}, "tracing": {"enabled": True}, "version": "version", }, chatkit_configuration={ "automatic_thread_titling": {"enabled": True}, "file_upload": { "enabled": True, "max_file_size": 1, "max_files": 1, }, "history": { "enabled": True, "recent_threads": 1, }, }, expires_after={ "anchor": "created_at", "seconds": 1, }, rate_limits={"max_requests_per_1_minute": 1}, ) assert_matches_type(ChatSession, session, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.beta.chatkit.sessions.with_raw_response.create( user="x", workflow={"id": "id"}, ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" session = response.parse() assert_matches_type(ChatSession, session, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.beta.chatkit.sessions.with_streaming_response.create( user="x", workflow={"id": "id"}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" session = response.parse() assert_matches_type(ChatSession, session, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_cancel(self, client: OpenAI) -> None: session = client.beta.chatkit.sessions.cancel( "cksess_123", ) assert_matches_type(ChatSession, session, path=["response"]) @parametrize def test_raw_response_cancel(self, client: OpenAI) -> None: response = client.beta.chatkit.sessions.with_raw_response.cancel( "cksess_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" session = response.parse() assert_matches_type(ChatSession, session, path=["response"]) @parametrize def test_streaming_response_cancel(self, client: OpenAI) -> None: with client.beta.chatkit.sessions.with_streaming_response.cancel( "cksess_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" session = response.parse() assert_matches_type(ChatSession, session, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_cancel(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): client.beta.chatkit.sessions.with_raw_response.cancel( "", ) class TestAsyncSessions: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: session = await async_client.beta.chatkit.sessions.create( user="x", workflow={"id": "id"}, ) assert_matches_type(ChatSession, session, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: session = await async_client.beta.chatkit.sessions.create( user="x", workflow={ "id": "id", "state_variables": {"foo": "string"}, "tracing": {"enabled": True}, "version": "version", }, chatkit_configuration={ "automatic_thread_titling": {"enabled": True}, "file_upload": { "enabled": True, "max_file_size": 1, "max_files": 1, }, "history": { "enabled": True, "recent_threads": 1, }, }, expires_after={ "anchor": "created_at", "seconds": 1, }, rate_limits={"max_requests_per_1_minute": 1}, ) assert_matches_type(ChatSession, session, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.beta.chatkit.sessions.with_raw_response.create( user="x", workflow={"id": "id"}, ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" session = response.parse() assert_matches_type(ChatSession, session, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.beta.chatkit.sessions.with_streaming_response.create( user="x", workflow={"id": "id"}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" session = await response.parse() assert_matches_type(ChatSession, session, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_cancel(self, async_client: AsyncOpenAI) -> None: session = await async_client.beta.chatkit.sessions.cancel( "cksess_123", ) assert_matches_type(ChatSession, session, path=["response"]) @parametrize async def test_raw_response_cancel(self, async_client: AsyncOpenAI) -> None: response = await async_client.beta.chatkit.sessions.with_raw_response.cancel( "cksess_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" session = response.parse() assert_matches_type(ChatSession, session, path=["response"]) @parametrize async def test_streaming_response_cancel(self, async_client: AsyncOpenAI) -> None: async with async_client.beta.chatkit.sessions.with_streaming_response.cancel( "cksess_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" session = await response.parse() assert_matches_type(ChatSession, session, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_cancel(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): await async_client.beta.chatkit.sessions.with_raw_response.cancel( "", ) ================================================ FILE: tests/api_resources/beta/chatkit/test_threads.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.pagination import SyncConversationCursorPage, AsyncConversationCursorPage from openai.types.beta.chatkit import ChatKitThread, ThreadDeleteResponse from openai.types.beta.chatkit.chatkit_thread_item_list import Data base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestThreads: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_retrieve(self, client: OpenAI) -> None: thread = client.beta.chatkit.threads.retrieve( "cthr_123", ) assert_matches_type(ChatKitThread, thread, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: response = client.beta.chatkit.threads.with_raw_response.retrieve( "cthr_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(ChatKitThread, thread, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with client.beta.chatkit.threads.with_streaming_response.retrieve( "cthr_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(ChatKitThread, thread, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.chatkit.threads.with_raw_response.retrieve( "", ) @parametrize def test_method_list(self, client: OpenAI) -> None: thread = client.beta.chatkit.threads.list() assert_matches_type(SyncConversationCursorPage[ChatKitThread], thread, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: thread = client.beta.chatkit.threads.list( after="after", before="before", limit=0, order="asc", user="x", ) assert_matches_type(SyncConversationCursorPage[ChatKitThread], thread, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.beta.chatkit.threads.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(SyncConversationCursorPage[ChatKitThread], thread, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.beta.chatkit.threads.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(SyncConversationCursorPage[ChatKitThread], thread, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_delete(self, client: OpenAI) -> None: thread = client.beta.chatkit.threads.delete( "cthr_123", ) assert_matches_type(ThreadDeleteResponse, thread, path=["response"]) @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: response = client.beta.chatkit.threads.with_raw_response.delete( "cthr_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(ThreadDeleteResponse, thread, path=["response"]) @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with client.beta.chatkit.threads.with_streaming_response.delete( "cthr_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(ThreadDeleteResponse, thread, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.chatkit.threads.with_raw_response.delete( "", ) @parametrize def test_method_list_items(self, client: OpenAI) -> None: thread = client.beta.chatkit.threads.list_items( thread_id="cthr_123", ) assert_matches_type(SyncConversationCursorPage[Data], thread, path=["response"]) @parametrize def test_method_list_items_with_all_params(self, client: OpenAI) -> None: thread = client.beta.chatkit.threads.list_items( thread_id="cthr_123", after="after", before="before", limit=0, order="asc", ) assert_matches_type(SyncConversationCursorPage[Data], thread, path=["response"]) @parametrize def test_raw_response_list_items(self, client: OpenAI) -> None: response = client.beta.chatkit.threads.with_raw_response.list_items( thread_id="cthr_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(SyncConversationCursorPage[Data], thread, path=["response"]) @parametrize def test_streaming_response_list_items(self, client: OpenAI) -> None: with client.beta.chatkit.threads.with_streaming_response.list_items( thread_id="cthr_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(SyncConversationCursorPage[Data], thread, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_list_items(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.chatkit.threads.with_raw_response.list_items( thread_id="", ) class TestAsyncThreads: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: thread = await async_client.beta.chatkit.threads.retrieve( "cthr_123", ) assert_matches_type(ChatKitThread, thread, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: response = await async_client.beta.chatkit.threads.with_raw_response.retrieve( "cthr_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(ChatKitThread, thread, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: async with async_client.beta.chatkit.threads.with_streaming_response.retrieve( "cthr_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = await response.parse() assert_matches_type(ChatKitThread, thread, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.chatkit.threads.with_raw_response.retrieve( "", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: thread = await async_client.beta.chatkit.threads.list() assert_matches_type(AsyncConversationCursorPage[ChatKitThread], thread, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: thread = await async_client.beta.chatkit.threads.list( after="after", before="before", limit=0, order="asc", user="x", ) assert_matches_type(AsyncConversationCursorPage[ChatKitThread], thread, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.beta.chatkit.threads.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(AsyncConversationCursorPage[ChatKitThread], thread, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.beta.chatkit.threads.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = await response.parse() assert_matches_type(AsyncConversationCursorPage[ChatKitThread], thread, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: thread = await async_client.beta.chatkit.threads.delete( "cthr_123", ) assert_matches_type(ThreadDeleteResponse, thread, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: response = await async_client.beta.chatkit.threads.with_raw_response.delete( "cthr_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(ThreadDeleteResponse, thread, path=["response"]) @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: async with async_client.beta.chatkit.threads.with_streaming_response.delete( "cthr_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = await response.parse() assert_matches_type(ThreadDeleteResponse, thread, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.chatkit.threads.with_raw_response.delete( "", ) @parametrize async def test_method_list_items(self, async_client: AsyncOpenAI) -> None: thread = await async_client.beta.chatkit.threads.list_items( thread_id="cthr_123", ) assert_matches_type(AsyncConversationCursorPage[Data], thread, path=["response"]) @parametrize async def test_method_list_items_with_all_params(self, async_client: AsyncOpenAI) -> None: thread = await async_client.beta.chatkit.threads.list_items( thread_id="cthr_123", after="after", before="before", limit=0, order="asc", ) assert_matches_type(AsyncConversationCursorPage[Data], thread, path=["response"]) @parametrize async def test_raw_response_list_items(self, async_client: AsyncOpenAI) -> None: response = await async_client.beta.chatkit.threads.with_raw_response.list_items( thread_id="cthr_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(AsyncConversationCursorPage[Data], thread, path=["response"]) @parametrize async def test_streaming_response_list_items(self, async_client: AsyncOpenAI) -> None: async with async_client.beta.chatkit.threads.with_streaming_response.list_items( thread_id="cthr_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = await response.parse() assert_matches_type(AsyncConversationCursorPage[Data], thread, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_list_items(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.chatkit.threads.with_raw_response.list_items( thread_id="", ) ================================================ FILE: tests/api_resources/beta/test_assistants.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.pagination import SyncCursorPage, AsyncCursorPage from openai.types.beta import ( Assistant, AssistantDeleted, ) # pyright: reportDeprecated=false base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestAssistants: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): assistant = client.beta.assistants.create( model="gpt-4o", ) assert_matches_type(Assistant, assistant, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): assistant = client.beta.assistants.create( model="gpt-4o", description="description", instructions="instructions", metadata={"foo": "string"}, name="name", reasoning_effort="none", response_format="auto", temperature=1, tool_resources={ "code_interpreter": {"file_ids": ["string"]}, "file_search": { "vector_store_ids": ["string"], "vector_stores": [ { "chunking_strategy": {"type": "auto"}, "file_ids": ["string"], "metadata": {"foo": "string"}, } ], }, }, tools=[{"type": "code_interpreter"}], top_p=1, ) assert_matches_type(Assistant, assistant, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.assistants.with_raw_response.create( model="gpt-4o", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = response.parse() assert_matches_type(Assistant, assistant, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.assistants.with_streaming_response.create( model="gpt-4o", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = response.parse() assert_matches_type(Assistant, assistant, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): assistant = client.beta.assistants.retrieve( "assistant_id", ) assert_matches_type(Assistant, assistant, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.assistants.with_raw_response.retrieve( "assistant_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = response.parse() assert_matches_type(Assistant, assistant, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.assistants.with_streaming_response.retrieve( "assistant_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = response.parse() assert_matches_type(Assistant, assistant, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `assistant_id` but received ''"): client.beta.assistants.with_raw_response.retrieve( "", ) @parametrize def test_method_update(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): assistant = client.beta.assistants.update( assistant_id="assistant_id", ) assert_matches_type(Assistant, assistant, path=["response"]) @parametrize def test_method_update_with_all_params(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): assistant = client.beta.assistants.update( assistant_id="assistant_id", description="description", instructions="instructions", metadata={"foo": "string"}, model="string", name="name", reasoning_effort="none", response_format="auto", temperature=1, tool_resources={ "code_interpreter": {"file_ids": ["string"]}, "file_search": {"vector_store_ids": ["string"]}, }, tools=[{"type": "code_interpreter"}], top_p=1, ) assert_matches_type(Assistant, assistant, path=["response"]) @parametrize def test_raw_response_update(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.assistants.with_raw_response.update( assistant_id="assistant_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = response.parse() assert_matches_type(Assistant, assistant, path=["response"]) @parametrize def test_streaming_response_update(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.assistants.with_streaming_response.update( assistant_id="assistant_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = response.parse() assert_matches_type(Assistant, assistant, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_update(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `assistant_id` but received ''"): client.beta.assistants.with_raw_response.update( assistant_id="", ) @parametrize def test_method_list(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): assistant = client.beta.assistants.list() assert_matches_type(SyncCursorPage[Assistant], assistant, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): assistant = client.beta.assistants.list( after="after", before="before", limit=0, order="asc", ) assert_matches_type(SyncCursorPage[Assistant], assistant, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.assistants.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = response.parse() assert_matches_type(SyncCursorPage[Assistant], assistant, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.assistants.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = response.parse() assert_matches_type(SyncCursorPage[Assistant], assistant, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_delete(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): assistant = client.beta.assistants.delete( "assistant_id", ) assert_matches_type(AssistantDeleted, assistant, path=["response"]) @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.assistants.with_raw_response.delete( "assistant_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = response.parse() assert_matches_type(AssistantDeleted, assistant, path=["response"]) @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.assistants.with_streaming_response.delete( "assistant_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = response.parse() assert_matches_type(AssistantDeleted, assistant, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `assistant_id` but received ''"): client.beta.assistants.with_raw_response.delete( "", ) class TestAsyncAssistants: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): assistant = await async_client.beta.assistants.create( model="gpt-4o", ) assert_matches_type(Assistant, assistant, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): assistant = await async_client.beta.assistants.create( model="gpt-4o", description="description", instructions="instructions", metadata={"foo": "string"}, name="name", reasoning_effort="none", response_format="auto", temperature=1, tool_resources={ "code_interpreter": {"file_ids": ["string"]}, "file_search": { "vector_store_ids": ["string"], "vector_stores": [ { "chunking_strategy": {"type": "auto"}, "file_ids": ["string"], "metadata": {"foo": "string"}, } ], }, }, tools=[{"type": "code_interpreter"}], top_p=1, ) assert_matches_type(Assistant, assistant, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.assistants.with_raw_response.create( model="gpt-4o", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = response.parse() assert_matches_type(Assistant, assistant, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.assistants.with_streaming_response.create( model="gpt-4o", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = await response.parse() assert_matches_type(Assistant, assistant, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): assistant = await async_client.beta.assistants.retrieve( "assistant_id", ) assert_matches_type(Assistant, assistant, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.assistants.with_raw_response.retrieve( "assistant_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = response.parse() assert_matches_type(Assistant, assistant, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.assistants.with_streaming_response.retrieve( "assistant_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = await response.parse() assert_matches_type(Assistant, assistant, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `assistant_id` but received ''"): await async_client.beta.assistants.with_raw_response.retrieve( "", ) @parametrize async def test_method_update(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): assistant = await async_client.beta.assistants.update( assistant_id="assistant_id", ) assert_matches_type(Assistant, assistant, path=["response"]) @parametrize async def test_method_update_with_all_params(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): assistant = await async_client.beta.assistants.update( assistant_id="assistant_id", description="description", instructions="instructions", metadata={"foo": "string"}, model="string", name="name", reasoning_effort="none", response_format="auto", temperature=1, tool_resources={ "code_interpreter": {"file_ids": ["string"]}, "file_search": {"vector_store_ids": ["string"]}, }, tools=[{"type": "code_interpreter"}], top_p=1, ) assert_matches_type(Assistant, assistant, path=["response"]) @parametrize async def test_raw_response_update(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.assistants.with_raw_response.update( assistant_id="assistant_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = response.parse() assert_matches_type(Assistant, assistant, path=["response"]) @parametrize async def test_streaming_response_update(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.assistants.with_streaming_response.update( assistant_id="assistant_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = await response.parse() assert_matches_type(Assistant, assistant, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_update(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `assistant_id` but received ''"): await async_client.beta.assistants.with_raw_response.update( assistant_id="", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): assistant = await async_client.beta.assistants.list() assert_matches_type(AsyncCursorPage[Assistant], assistant, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): assistant = await async_client.beta.assistants.list( after="after", before="before", limit=0, order="asc", ) assert_matches_type(AsyncCursorPage[Assistant], assistant, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.assistants.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = response.parse() assert_matches_type(AsyncCursorPage[Assistant], assistant, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.assistants.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = await response.parse() assert_matches_type(AsyncCursorPage[Assistant], assistant, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): assistant = await async_client.beta.assistants.delete( "assistant_id", ) assert_matches_type(AssistantDeleted, assistant, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.assistants.with_raw_response.delete( "assistant_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = response.parse() assert_matches_type(AssistantDeleted, assistant, path=["response"]) @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.assistants.with_streaming_response.delete( "assistant_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" assistant = await response.parse() assert_matches_type(AssistantDeleted, assistant, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `assistant_id` but received ''"): await async_client.beta.assistants.with_raw_response.delete( "", ) ================================================ FILE: tests/api_resources/beta/test_realtime.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os import pytest # pyright: reportDeprecated=false base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestRealtime: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) class TestAsyncRealtime: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) ================================================ FILE: tests/api_resources/beta/test_threads.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types.beta import ( Thread, ThreadDeleted, ) from openai.types.beta.threads import Run # pyright: reportDeprecated=false base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestThreads: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): thread = client.beta.threads.create() assert_matches_type(Thread, thread, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): thread = client.beta.threads.create( messages=[ { "content": "string", "role": "user", "attachments": [ { "file_id": "file_id", "tools": [{"type": "code_interpreter"}], } ], "metadata": {"foo": "string"}, } ], metadata={"foo": "string"}, tool_resources={ "code_interpreter": {"file_ids": ["string"]}, "file_search": { "vector_store_ids": ["string"], "vector_stores": [ { "chunking_strategy": {"type": "auto"}, "file_ids": ["string"], "metadata": {"foo": "string"}, } ], }, }, ) assert_matches_type(Thread, thread, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.with_raw_response.create() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(Thread, thread, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.with_streaming_response.create() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(Thread, thread, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): thread = client.beta.threads.retrieve( "thread_id", ) assert_matches_type(Thread, thread, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.with_raw_response.retrieve( "thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(Thread, thread, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.with_streaming_response.retrieve( "thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(Thread, thread, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.threads.with_raw_response.retrieve( "", ) @parametrize def test_method_update(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): thread = client.beta.threads.update( thread_id="thread_id", ) assert_matches_type(Thread, thread, path=["response"]) @parametrize def test_method_update_with_all_params(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): thread = client.beta.threads.update( thread_id="thread_id", metadata={"foo": "string"}, tool_resources={ "code_interpreter": {"file_ids": ["string"]}, "file_search": {"vector_store_ids": ["string"]}, }, ) assert_matches_type(Thread, thread, path=["response"]) @parametrize def test_raw_response_update(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.with_raw_response.update( thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(Thread, thread, path=["response"]) @parametrize def test_streaming_response_update(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.with_streaming_response.update( thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(Thread, thread, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_update(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.threads.with_raw_response.update( thread_id="", ) @parametrize def test_method_delete(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): thread = client.beta.threads.delete( "thread_id", ) assert_matches_type(ThreadDeleted, thread, path=["response"]) @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.with_raw_response.delete( "thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(ThreadDeleted, thread, path=["response"]) @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.with_streaming_response.delete( "thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(ThreadDeleted, thread, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.threads.with_raw_response.delete( "", ) @parametrize def test_method_create_and_run_overload_1(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): thread = client.beta.threads.create_and_run( assistant_id="assistant_id", ) assert_matches_type(Run, thread, path=["response"]) @parametrize def test_method_create_and_run_with_all_params_overload_1(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): thread = client.beta.threads.create_and_run( assistant_id="assistant_id", instructions="instructions", max_completion_tokens=256, max_prompt_tokens=256, metadata={"foo": "string"}, model="string", parallel_tool_calls=True, response_format="auto", stream=False, temperature=1, thread={ "messages": [ { "content": "string", "role": "user", "attachments": [ { "file_id": "file_id", "tools": [{"type": "code_interpreter"}], } ], "metadata": {"foo": "string"}, } ], "metadata": {"foo": "string"}, "tool_resources": { "code_interpreter": {"file_ids": ["string"]}, "file_search": { "vector_store_ids": ["string"], "vector_stores": [ { "chunking_strategy": {"type": "auto"}, "file_ids": ["string"], "metadata": {"foo": "string"}, } ], }, }, }, tool_choice="none", tool_resources={ "code_interpreter": {"file_ids": ["string"]}, "file_search": {"vector_store_ids": ["string"]}, }, tools=[{"type": "code_interpreter"}], top_p=1, truncation_strategy={ "type": "auto", "last_messages": 1, }, ) assert_matches_type(Run, thread, path=["response"]) @parametrize def test_raw_response_create_and_run_overload_1(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.with_raw_response.create_and_run( assistant_id="assistant_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(Run, thread, path=["response"]) @parametrize def test_streaming_response_create_and_run_overload_1(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.with_streaming_response.create_and_run( assistant_id="assistant_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(Run, thread, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_create_and_run_overload_2(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): thread_stream = client.beta.threads.create_and_run( assistant_id="assistant_id", stream=True, ) thread_stream.response.close() @parametrize def test_method_create_and_run_with_all_params_overload_2(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): thread_stream = client.beta.threads.create_and_run( assistant_id="assistant_id", stream=True, instructions="instructions", max_completion_tokens=256, max_prompt_tokens=256, metadata={"foo": "string"}, model="string", parallel_tool_calls=True, response_format="auto", temperature=1, thread={ "messages": [ { "content": "string", "role": "user", "attachments": [ { "file_id": "file_id", "tools": [{"type": "code_interpreter"}], } ], "metadata": {"foo": "string"}, } ], "metadata": {"foo": "string"}, "tool_resources": { "code_interpreter": {"file_ids": ["string"]}, "file_search": { "vector_store_ids": ["string"], "vector_stores": [ { "chunking_strategy": {"type": "auto"}, "file_ids": ["string"], "metadata": {"foo": "string"}, } ], }, }, }, tool_choice="none", tool_resources={ "code_interpreter": {"file_ids": ["string"]}, "file_search": {"vector_store_ids": ["string"]}, }, tools=[{"type": "code_interpreter"}], top_p=1, truncation_strategy={ "type": "auto", "last_messages": 1, }, ) thread_stream.response.close() @parametrize def test_raw_response_create_and_run_overload_2(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.with_raw_response.create_and_run( assistant_id="assistant_id", stream=True, ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() @parametrize def test_streaming_response_create_and_run_overload_2(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.with_streaming_response.create_and_run( assistant_id="assistant_id", stream=True, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() assert cast(Any, response.is_closed) is True class TestAsyncThreads: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): thread = await async_client.beta.threads.create() assert_matches_type(Thread, thread, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): thread = await async_client.beta.threads.create( messages=[ { "content": "string", "role": "user", "attachments": [ { "file_id": "file_id", "tools": [{"type": "code_interpreter"}], } ], "metadata": {"foo": "string"}, } ], metadata={"foo": "string"}, tool_resources={ "code_interpreter": {"file_ids": ["string"]}, "file_search": { "vector_store_ids": ["string"], "vector_stores": [ { "chunking_strategy": {"type": "auto"}, "file_ids": ["string"], "metadata": {"foo": "string"}, } ], }, }, ) assert_matches_type(Thread, thread, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.with_raw_response.create() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(Thread, thread, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.with_streaming_response.create() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = await response.parse() assert_matches_type(Thread, thread, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): thread = await async_client.beta.threads.retrieve( "thread_id", ) assert_matches_type(Thread, thread, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.with_raw_response.retrieve( "thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(Thread, thread, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.with_streaming_response.retrieve( "thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = await response.parse() assert_matches_type(Thread, thread, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.threads.with_raw_response.retrieve( "", ) @parametrize async def test_method_update(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): thread = await async_client.beta.threads.update( thread_id="thread_id", ) assert_matches_type(Thread, thread, path=["response"]) @parametrize async def test_method_update_with_all_params(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): thread = await async_client.beta.threads.update( thread_id="thread_id", metadata={"foo": "string"}, tool_resources={ "code_interpreter": {"file_ids": ["string"]}, "file_search": {"vector_store_ids": ["string"]}, }, ) assert_matches_type(Thread, thread, path=["response"]) @parametrize async def test_raw_response_update(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.with_raw_response.update( thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(Thread, thread, path=["response"]) @parametrize async def test_streaming_response_update(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.with_streaming_response.update( thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = await response.parse() assert_matches_type(Thread, thread, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_update(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.threads.with_raw_response.update( thread_id="", ) @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): thread = await async_client.beta.threads.delete( "thread_id", ) assert_matches_type(ThreadDeleted, thread, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.with_raw_response.delete( "thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(ThreadDeleted, thread, path=["response"]) @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.with_streaming_response.delete( "thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = await response.parse() assert_matches_type(ThreadDeleted, thread, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.threads.with_raw_response.delete( "", ) @parametrize async def test_method_create_and_run_overload_1(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): thread = await async_client.beta.threads.create_and_run( assistant_id="assistant_id", ) assert_matches_type(Run, thread, path=["response"]) @parametrize async def test_method_create_and_run_with_all_params_overload_1(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): thread = await async_client.beta.threads.create_and_run( assistant_id="assistant_id", instructions="instructions", max_completion_tokens=256, max_prompt_tokens=256, metadata={"foo": "string"}, model="string", parallel_tool_calls=True, response_format="auto", stream=False, temperature=1, thread={ "messages": [ { "content": "string", "role": "user", "attachments": [ { "file_id": "file_id", "tools": [{"type": "code_interpreter"}], } ], "metadata": {"foo": "string"}, } ], "metadata": {"foo": "string"}, "tool_resources": { "code_interpreter": {"file_ids": ["string"]}, "file_search": { "vector_store_ids": ["string"], "vector_stores": [ { "chunking_strategy": {"type": "auto"}, "file_ids": ["string"], "metadata": {"foo": "string"}, } ], }, }, }, tool_choice="none", tool_resources={ "code_interpreter": {"file_ids": ["string"]}, "file_search": {"vector_store_ids": ["string"]}, }, tools=[{"type": "code_interpreter"}], top_p=1, truncation_strategy={ "type": "auto", "last_messages": 1, }, ) assert_matches_type(Run, thread, path=["response"]) @parametrize async def test_raw_response_create_and_run_overload_1(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.with_raw_response.create_and_run( assistant_id="assistant_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = response.parse() assert_matches_type(Run, thread, path=["response"]) @parametrize async def test_streaming_response_create_and_run_overload_1(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.with_streaming_response.create_and_run( assistant_id="assistant_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" thread = await response.parse() assert_matches_type(Run, thread, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_create_and_run_overload_2(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): thread_stream = await async_client.beta.threads.create_and_run( assistant_id="assistant_id", stream=True, ) await thread_stream.response.aclose() @parametrize async def test_method_create_and_run_with_all_params_overload_2(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): thread_stream = await async_client.beta.threads.create_and_run( assistant_id="assistant_id", stream=True, instructions="instructions", max_completion_tokens=256, max_prompt_tokens=256, metadata={"foo": "string"}, model="string", parallel_tool_calls=True, response_format="auto", temperature=1, thread={ "messages": [ { "content": "string", "role": "user", "attachments": [ { "file_id": "file_id", "tools": [{"type": "code_interpreter"}], } ], "metadata": {"foo": "string"}, } ], "metadata": {"foo": "string"}, "tool_resources": { "code_interpreter": {"file_ids": ["string"]}, "file_search": { "vector_store_ids": ["string"], "vector_stores": [ { "chunking_strategy": {"type": "auto"}, "file_ids": ["string"], "metadata": {"foo": "string"}, } ], }, }, }, tool_choice="none", tool_resources={ "code_interpreter": {"file_ids": ["string"]}, "file_search": {"vector_store_ids": ["string"]}, }, tools=[{"type": "code_interpreter"}], top_p=1, truncation_strategy={ "type": "auto", "last_messages": 1, }, ) await thread_stream.response.aclose() @parametrize async def test_raw_response_create_and_run_overload_2(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.with_raw_response.create_and_run( assistant_id="assistant_id", stream=True, ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() await stream.close() @parametrize async def test_streaming_response_create_and_run_overload_2(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.with_streaming_response.create_and_run( assistant_id="assistant_id", stream=True, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = await response.parse() await stream.close() assert cast(Any, response.is_closed) is True ================================================ FILE: tests/api_resources/beta/threads/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/beta/threads/runs/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/beta/threads/runs/test_steps.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.pagination import SyncCursorPage, AsyncCursorPage from openai.types.beta.threads.runs import RunStep # pyright: reportDeprecated=false base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestSteps: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): step = client.beta.threads.runs.steps.retrieve( step_id="step_id", thread_id="thread_id", run_id="run_id", ) assert_matches_type(RunStep, step, path=["response"]) @parametrize def test_method_retrieve_with_all_params(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): step = client.beta.threads.runs.steps.retrieve( step_id="step_id", thread_id="thread_id", run_id="run_id", include=["step_details.tool_calls[*].file_search.results[*].content"], ) assert_matches_type(RunStep, step, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.runs.steps.with_raw_response.retrieve( step_id="step_id", thread_id="thread_id", run_id="run_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" step = response.parse() assert_matches_type(RunStep, step, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.runs.steps.with_streaming_response.retrieve( step_id="step_id", thread_id="thread_id", run_id="run_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" step = response.parse() assert_matches_type(RunStep, step, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.threads.runs.steps.with_raw_response.retrieve( step_id="step_id", thread_id="", run_id="run_id", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): client.beta.threads.runs.steps.with_raw_response.retrieve( step_id="step_id", thread_id="thread_id", run_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `step_id` but received ''"): client.beta.threads.runs.steps.with_raw_response.retrieve( step_id="", thread_id="thread_id", run_id="run_id", ) @parametrize def test_method_list(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): step = client.beta.threads.runs.steps.list( run_id="run_id", thread_id="thread_id", ) assert_matches_type(SyncCursorPage[RunStep], step, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): step = client.beta.threads.runs.steps.list( run_id="run_id", thread_id="thread_id", after="after", before="before", include=["step_details.tool_calls[*].file_search.results[*].content"], limit=0, order="asc", ) assert_matches_type(SyncCursorPage[RunStep], step, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.runs.steps.with_raw_response.list( run_id="run_id", thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" step = response.parse() assert_matches_type(SyncCursorPage[RunStep], step, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.runs.steps.with_streaming_response.list( run_id="run_id", thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" step = response.parse() assert_matches_type(SyncCursorPage[RunStep], step, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_list(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.threads.runs.steps.with_raw_response.list( run_id="run_id", thread_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): client.beta.threads.runs.steps.with_raw_response.list( run_id="", thread_id="thread_id", ) class TestAsyncSteps: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): step = await async_client.beta.threads.runs.steps.retrieve( step_id="step_id", thread_id="thread_id", run_id="run_id", ) assert_matches_type(RunStep, step, path=["response"]) @parametrize async def test_method_retrieve_with_all_params(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): step = await async_client.beta.threads.runs.steps.retrieve( step_id="step_id", thread_id="thread_id", run_id="run_id", include=["step_details.tool_calls[*].file_search.results[*].content"], ) assert_matches_type(RunStep, step, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.runs.steps.with_raw_response.retrieve( step_id="step_id", thread_id="thread_id", run_id="run_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" step = response.parse() assert_matches_type(RunStep, step, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.runs.steps.with_streaming_response.retrieve( step_id="step_id", thread_id="thread_id", run_id="run_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" step = await response.parse() assert_matches_type(RunStep, step, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.threads.runs.steps.with_raw_response.retrieve( step_id="step_id", thread_id="", run_id="run_id", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): await async_client.beta.threads.runs.steps.with_raw_response.retrieve( step_id="step_id", thread_id="thread_id", run_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `step_id` but received ''"): await async_client.beta.threads.runs.steps.with_raw_response.retrieve( step_id="", thread_id="thread_id", run_id="run_id", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): step = await async_client.beta.threads.runs.steps.list( run_id="run_id", thread_id="thread_id", ) assert_matches_type(AsyncCursorPage[RunStep], step, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): step = await async_client.beta.threads.runs.steps.list( run_id="run_id", thread_id="thread_id", after="after", before="before", include=["step_details.tool_calls[*].file_search.results[*].content"], limit=0, order="asc", ) assert_matches_type(AsyncCursorPage[RunStep], step, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.runs.steps.with_raw_response.list( run_id="run_id", thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" step = response.parse() assert_matches_type(AsyncCursorPage[RunStep], step, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.runs.steps.with_streaming_response.list( run_id="run_id", thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" step = await response.parse() assert_matches_type(AsyncCursorPage[RunStep], step, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_list(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.threads.runs.steps.with_raw_response.list( run_id="run_id", thread_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): await async_client.beta.threads.runs.steps.with_raw_response.list( run_id="", thread_id="thread_id", ) ================================================ FILE: tests/api_resources/beta/threads/test_messages.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.pagination import SyncCursorPage, AsyncCursorPage from openai.types.beta.threads import ( Message, MessageDeleted, ) # pyright: reportDeprecated=false base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestMessages: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): message = client.beta.threads.messages.create( thread_id="thread_id", content="string", role="user", ) assert_matches_type(Message, message, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): message = client.beta.threads.messages.create( thread_id="thread_id", content="string", role="user", attachments=[ { "file_id": "file_id", "tools": [{"type": "code_interpreter"}], } ], metadata={"foo": "string"}, ) assert_matches_type(Message, message, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.messages.with_raw_response.create( thread_id="thread_id", content="string", role="user", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = response.parse() assert_matches_type(Message, message, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.messages.with_streaming_response.create( thread_id="thread_id", content="string", role="user", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = response.parse() assert_matches_type(Message, message, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_create(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.threads.messages.with_raw_response.create( thread_id="", content="string", role="user", ) @parametrize def test_method_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): message = client.beta.threads.messages.retrieve( message_id="message_id", thread_id="thread_id", ) assert_matches_type(Message, message, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.messages.with_raw_response.retrieve( message_id="message_id", thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = response.parse() assert_matches_type(Message, message, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.messages.with_streaming_response.retrieve( message_id="message_id", thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = response.parse() assert_matches_type(Message, message, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.threads.messages.with_raw_response.retrieve( message_id="message_id", thread_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"): client.beta.threads.messages.with_raw_response.retrieve( message_id="", thread_id="thread_id", ) @parametrize def test_method_update(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): message = client.beta.threads.messages.update( message_id="message_id", thread_id="thread_id", ) assert_matches_type(Message, message, path=["response"]) @parametrize def test_method_update_with_all_params(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): message = client.beta.threads.messages.update( message_id="message_id", thread_id="thread_id", metadata={"foo": "string"}, ) assert_matches_type(Message, message, path=["response"]) @parametrize def test_raw_response_update(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.messages.with_raw_response.update( message_id="message_id", thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = response.parse() assert_matches_type(Message, message, path=["response"]) @parametrize def test_streaming_response_update(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.messages.with_streaming_response.update( message_id="message_id", thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = response.parse() assert_matches_type(Message, message, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_update(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.threads.messages.with_raw_response.update( message_id="message_id", thread_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"): client.beta.threads.messages.with_raw_response.update( message_id="", thread_id="thread_id", ) @parametrize def test_method_list(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): message = client.beta.threads.messages.list( thread_id="thread_id", ) assert_matches_type(SyncCursorPage[Message], message, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): message = client.beta.threads.messages.list( thread_id="thread_id", after="after", before="before", limit=0, order="asc", run_id="run_id", ) assert_matches_type(SyncCursorPage[Message], message, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.messages.with_raw_response.list( thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = response.parse() assert_matches_type(SyncCursorPage[Message], message, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.messages.with_streaming_response.list( thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = response.parse() assert_matches_type(SyncCursorPage[Message], message, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_list(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.threads.messages.with_raw_response.list( thread_id="", ) @parametrize def test_method_delete(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): message = client.beta.threads.messages.delete( message_id="message_id", thread_id="thread_id", ) assert_matches_type(MessageDeleted, message, path=["response"]) @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.messages.with_raw_response.delete( message_id="message_id", thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = response.parse() assert_matches_type(MessageDeleted, message, path=["response"]) @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.messages.with_streaming_response.delete( message_id="message_id", thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = response.parse() assert_matches_type(MessageDeleted, message, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.threads.messages.with_raw_response.delete( message_id="message_id", thread_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"): client.beta.threads.messages.with_raw_response.delete( message_id="", thread_id="thread_id", ) class TestAsyncMessages: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): message = await async_client.beta.threads.messages.create( thread_id="thread_id", content="string", role="user", ) assert_matches_type(Message, message, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): message = await async_client.beta.threads.messages.create( thread_id="thread_id", content="string", role="user", attachments=[ { "file_id": "file_id", "tools": [{"type": "code_interpreter"}], } ], metadata={"foo": "string"}, ) assert_matches_type(Message, message, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.messages.with_raw_response.create( thread_id="thread_id", content="string", role="user", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = response.parse() assert_matches_type(Message, message, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.messages.with_streaming_response.create( thread_id="thread_id", content="string", role="user", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = await response.parse() assert_matches_type(Message, message, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_create(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.threads.messages.with_raw_response.create( thread_id="", content="string", role="user", ) @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): message = await async_client.beta.threads.messages.retrieve( message_id="message_id", thread_id="thread_id", ) assert_matches_type(Message, message, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.messages.with_raw_response.retrieve( message_id="message_id", thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = response.parse() assert_matches_type(Message, message, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.messages.with_streaming_response.retrieve( message_id="message_id", thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = await response.parse() assert_matches_type(Message, message, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.threads.messages.with_raw_response.retrieve( message_id="message_id", thread_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"): await async_client.beta.threads.messages.with_raw_response.retrieve( message_id="", thread_id="thread_id", ) @parametrize async def test_method_update(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): message = await async_client.beta.threads.messages.update( message_id="message_id", thread_id="thread_id", ) assert_matches_type(Message, message, path=["response"]) @parametrize async def test_method_update_with_all_params(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): message = await async_client.beta.threads.messages.update( message_id="message_id", thread_id="thread_id", metadata={"foo": "string"}, ) assert_matches_type(Message, message, path=["response"]) @parametrize async def test_raw_response_update(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.messages.with_raw_response.update( message_id="message_id", thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = response.parse() assert_matches_type(Message, message, path=["response"]) @parametrize async def test_streaming_response_update(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.messages.with_streaming_response.update( message_id="message_id", thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = await response.parse() assert_matches_type(Message, message, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_update(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.threads.messages.with_raw_response.update( message_id="message_id", thread_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"): await async_client.beta.threads.messages.with_raw_response.update( message_id="", thread_id="thread_id", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): message = await async_client.beta.threads.messages.list( thread_id="thread_id", ) assert_matches_type(AsyncCursorPage[Message], message, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): message = await async_client.beta.threads.messages.list( thread_id="thread_id", after="after", before="before", limit=0, order="asc", run_id="run_id", ) assert_matches_type(AsyncCursorPage[Message], message, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.messages.with_raw_response.list( thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = response.parse() assert_matches_type(AsyncCursorPage[Message], message, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.messages.with_streaming_response.list( thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = await response.parse() assert_matches_type(AsyncCursorPage[Message], message, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_list(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.threads.messages.with_raw_response.list( thread_id="", ) @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): message = await async_client.beta.threads.messages.delete( message_id="message_id", thread_id="thread_id", ) assert_matches_type(MessageDeleted, message, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.messages.with_raw_response.delete( message_id="message_id", thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = response.parse() assert_matches_type(MessageDeleted, message, path=["response"]) @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.messages.with_streaming_response.delete( message_id="message_id", thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = await response.parse() assert_matches_type(MessageDeleted, message, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.threads.messages.with_raw_response.delete( message_id="message_id", thread_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"): await async_client.beta.threads.messages.with_raw_response.delete( message_id="", thread_id="thread_id", ) ================================================ FILE: tests/api_resources/beta/threads/test_runs.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.pagination import SyncCursorPage, AsyncCursorPage from openai.types.beta.threads import ( Run, ) # pyright: reportDeprecated=false base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestRuns: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create_overload_1(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): run = client.beta.threads.runs.create( thread_id="thread_id", assistant_id="assistant_id", ) assert_matches_type(Run, run, path=["response"]) @parametrize def test_method_create_with_all_params_overload_1(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): run = client.beta.threads.runs.create( thread_id="thread_id", assistant_id="assistant_id", include=["step_details.tool_calls[*].file_search.results[*].content"], additional_instructions="additional_instructions", additional_messages=[ { "content": "string", "role": "user", "attachments": [ { "file_id": "file_id", "tools": [{"type": "code_interpreter"}], } ], "metadata": {"foo": "string"}, } ], instructions="instructions", max_completion_tokens=256, max_prompt_tokens=256, metadata={"foo": "string"}, model="string", parallel_tool_calls=True, reasoning_effort="none", response_format="auto", stream=False, temperature=1, tool_choice="none", tools=[{"type": "code_interpreter"}], top_p=1, truncation_strategy={ "type": "auto", "last_messages": 1, }, ) assert_matches_type(Run, run, path=["response"]) @parametrize def test_raw_response_create_overload_1(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.runs.with_raw_response.create( thread_id="thread_id", assistant_id="assistant_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(Run, run, path=["response"]) @parametrize def test_streaming_response_create_overload_1(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.runs.with_streaming_response.create( thread_id="thread_id", assistant_id="assistant_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(Run, run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_create_overload_1(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.threads.runs.with_raw_response.create( thread_id="", assistant_id="assistant_id", ) @parametrize def test_method_create_overload_2(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): run_stream = client.beta.threads.runs.create( thread_id="thread_id", assistant_id="assistant_id", stream=True, ) run_stream.response.close() @parametrize def test_method_create_with_all_params_overload_2(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): run_stream = client.beta.threads.runs.create( thread_id="thread_id", assistant_id="assistant_id", stream=True, include=["step_details.tool_calls[*].file_search.results[*].content"], additional_instructions="additional_instructions", additional_messages=[ { "content": "string", "role": "user", "attachments": [ { "file_id": "file_id", "tools": [{"type": "code_interpreter"}], } ], "metadata": {"foo": "string"}, } ], instructions="instructions", max_completion_tokens=256, max_prompt_tokens=256, metadata={"foo": "string"}, model="string", parallel_tool_calls=True, reasoning_effort="none", response_format="auto", temperature=1, tool_choice="none", tools=[{"type": "code_interpreter"}], top_p=1, truncation_strategy={ "type": "auto", "last_messages": 1, }, ) run_stream.response.close() @parametrize def test_raw_response_create_overload_2(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.runs.with_raw_response.create( thread_id="thread_id", assistant_id="assistant_id", stream=True, ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() @parametrize def test_streaming_response_create_overload_2(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.runs.with_streaming_response.create( thread_id="thread_id", assistant_id="assistant_id", stream=True, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() assert cast(Any, response.is_closed) is True @parametrize def test_path_params_create_overload_2(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.threads.runs.with_raw_response.create( thread_id="", assistant_id="assistant_id", stream=True, ) @parametrize def test_method_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): run = client.beta.threads.runs.retrieve( run_id="run_id", thread_id="thread_id", ) assert_matches_type(Run, run, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.runs.with_raw_response.retrieve( run_id="run_id", thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(Run, run, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.runs.with_streaming_response.retrieve( run_id="run_id", thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(Run, run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.threads.runs.with_raw_response.retrieve( run_id="run_id", thread_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): client.beta.threads.runs.with_raw_response.retrieve( run_id="", thread_id="thread_id", ) @parametrize def test_method_update(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): run = client.beta.threads.runs.update( run_id="run_id", thread_id="thread_id", ) assert_matches_type(Run, run, path=["response"]) @parametrize def test_method_update_with_all_params(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): run = client.beta.threads.runs.update( run_id="run_id", thread_id="thread_id", metadata={"foo": "string"}, ) assert_matches_type(Run, run, path=["response"]) @parametrize def test_raw_response_update(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.runs.with_raw_response.update( run_id="run_id", thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(Run, run, path=["response"]) @parametrize def test_streaming_response_update(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.runs.with_streaming_response.update( run_id="run_id", thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(Run, run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_update(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.threads.runs.with_raw_response.update( run_id="run_id", thread_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): client.beta.threads.runs.with_raw_response.update( run_id="", thread_id="thread_id", ) @parametrize def test_method_list(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): run = client.beta.threads.runs.list( thread_id="thread_id", ) assert_matches_type(SyncCursorPage[Run], run, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): run = client.beta.threads.runs.list( thread_id="thread_id", after="after", before="before", limit=0, order="asc", ) assert_matches_type(SyncCursorPage[Run], run, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.runs.with_raw_response.list( thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(SyncCursorPage[Run], run, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.runs.with_streaming_response.list( thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(SyncCursorPage[Run], run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_list(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.threads.runs.with_raw_response.list( thread_id="", ) @parametrize def test_method_cancel(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): run = client.beta.threads.runs.cancel( run_id="run_id", thread_id="thread_id", ) assert_matches_type(Run, run, path=["response"]) @parametrize def test_raw_response_cancel(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.runs.with_raw_response.cancel( run_id="run_id", thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(Run, run, path=["response"]) @parametrize def test_streaming_response_cancel(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.runs.with_streaming_response.cancel( run_id="run_id", thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(Run, run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_cancel(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.threads.runs.with_raw_response.cancel( run_id="run_id", thread_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): client.beta.threads.runs.with_raw_response.cancel( run_id="", thread_id="thread_id", ) @parametrize def test_method_submit_tool_outputs_overload_1(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): run = client.beta.threads.runs.submit_tool_outputs( run_id="run_id", thread_id="thread_id", tool_outputs=[{}], ) assert_matches_type(Run, run, path=["response"]) @parametrize def test_method_submit_tool_outputs_with_all_params_overload_1(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): run = client.beta.threads.runs.submit_tool_outputs( run_id="run_id", thread_id="thread_id", tool_outputs=[ { "output": "output", "tool_call_id": "tool_call_id", } ], stream=False, ) assert_matches_type(Run, run, path=["response"]) @parametrize def test_raw_response_submit_tool_outputs_overload_1(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.runs.with_raw_response.submit_tool_outputs( run_id="run_id", thread_id="thread_id", tool_outputs=[{}], ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(Run, run, path=["response"]) @parametrize def test_streaming_response_submit_tool_outputs_overload_1(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.runs.with_streaming_response.submit_tool_outputs( run_id="run_id", thread_id="thread_id", tool_outputs=[{}], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(Run, run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_submit_tool_outputs_overload_1(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.threads.runs.with_raw_response.submit_tool_outputs( run_id="run_id", thread_id="", tool_outputs=[{}], ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): client.beta.threads.runs.with_raw_response.submit_tool_outputs( run_id="", thread_id="thread_id", tool_outputs=[{}], ) @parametrize def test_method_submit_tool_outputs_overload_2(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): run_stream = client.beta.threads.runs.submit_tool_outputs( run_id="run_id", thread_id="thread_id", stream=True, tool_outputs=[{}], ) run_stream.response.close() @parametrize def test_raw_response_submit_tool_outputs_overload_2(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.beta.threads.runs.with_raw_response.submit_tool_outputs( run_id="run_id", thread_id="thread_id", stream=True, tool_outputs=[{}], ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() @parametrize def test_streaming_response_submit_tool_outputs_overload_2(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.beta.threads.runs.with_streaming_response.submit_tool_outputs( run_id="run_id", thread_id="thread_id", stream=True, tool_outputs=[{}], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() assert cast(Any, response.is_closed) is True @parametrize def test_path_params_submit_tool_outputs_overload_2(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): client.beta.threads.runs.with_raw_response.submit_tool_outputs( run_id="run_id", thread_id="", stream=True, tool_outputs=[{}], ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): client.beta.threads.runs.with_raw_response.submit_tool_outputs( run_id="", thread_id="thread_id", stream=True, tool_outputs=[{}], ) class TestAsyncRuns: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create_overload_1(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): run = await async_client.beta.threads.runs.create( thread_id="thread_id", assistant_id="assistant_id", ) assert_matches_type(Run, run, path=["response"]) @parametrize async def test_method_create_with_all_params_overload_1(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): run = await async_client.beta.threads.runs.create( thread_id="thread_id", assistant_id="assistant_id", include=["step_details.tool_calls[*].file_search.results[*].content"], additional_instructions="additional_instructions", additional_messages=[ { "content": "string", "role": "user", "attachments": [ { "file_id": "file_id", "tools": [{"type": "code_interpreter"}], } ], "metadata": {"foo": "string"}, } ], instructions="instructions", max_completion_tokens=256, max_prompt_tokens=256, metadata={"foo": "string"}, model="string", parallel_tool_calls=True, reasoning_effort="none", response_format="auto", stream=False, temperature=1, tool_choice="none", tools=[{"type": "code_interpreter"}], top_p=1, truncation_strategy={ "type": "auto", "last_messages": 1, }, ) assert_matches_type(Run, run, path=["response"]) @parametrize async def test_raw_response_create_overload_1(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.runs.with_raw_response.create( thread_id="thread_id", assistant_id="assistant_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(Run, run, path=["response"]) @parametrize async def test_streaming_response_create_overload_1(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.runs.with_streaming_response.create( thread_id="thread_id", assistant_id="assistant_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() assert_matches_type(Run, run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_create_overload_1(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.threads.runs.with_raw_response.create( thread_id="", assistant_id="assistant_id", ) @parametrize async def test_method_create_overload_2(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): run_stream = await async_client.beta.threads.runs.create( thread_id="thread_id", assistant_id="assistant_id", stream=True, ) await run_stream.response.aclose() @parametrize async def test_method_create_with_all_params_overload_2(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): run_stream = await async_client.beta.threads.runs.create( thread_id="thread_id", assistant_id="assistant_id", stream=True, include=["step_details.tool_calls[*].file_search.results[*].content"], additional_instructions="additional_instructions", additional_messages=[ { "content": "string", "role": "user", "attachments": [ { "file_id": "file_id", "tools": [{"type": "code_interpreter"}], } ], "metadata": {"foo": "string"}, } ], instructions="instructions", max_completion_tokens=256, max_prompt_tokens=256, metadata={"foo": "string"}, model="string", parallel_tool_calls=True, reasoning_effort="none", response_format="auto", temperature=1, tool_choice="none", tools=[{"type": "code_interpreter"}], top_p=1, truncation_strategy={ "type": "auto", "last_messages": 1, }, ) await run_stream.response.aclose() @parametrize async def test_raw_response_create_overload_2(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.runs.with_raw_response.create( thread_id="thread_id", assistant_id="assistant_id", stream=True, ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() await stream.close() @parametrize async def test_streaming_response_create_overload_2(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.runs.with_streaming_response.create( thread_id="thread_id", assistant_id="assistant_id", stream=True, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = await response.parse() await stream.close() assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_create_overload_2(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.threads.runs.with_raw_response.create( thread_id="", assistant_id="assistant_id", stream=True, ) @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): run = await async_client.beta.threads.runs.retrieve( run_id="run_id", thread_id="thread_id", ) assert_matches_type(Run, run, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.runs.with_raw_response.retrieve( run_id="run_id", thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(Run, run, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.runs.with_streaming_response.retrieve( run_id="run_id", thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() assert_matches_type(Run, run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.threads.runs.with_raw_response.retrieve( run_id="run_id", thread_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): await async_client.beta.threads.runs.with_raw_response.retrieve( run_id="", thread_id="thread_id", ) @parametrize async def test_method_update(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): run = await async_client.beta.threads.runs.update( run_id="run_id", thread_id="thread_id", ) assert_matches_type(Run, run, path=["response"]) @parametrize async def test_method_update_with_all_params(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): run = await async_client.beta.threads.runs.update( run_id="run_id", thread_id="thread_id", metadata={"foo": "string"}, ) assert_matches_type(Run, run, path=["response"]) @parametrize async def test_raw_response_update(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.runs.with_raw_response.update( run_id="run_id", thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(Run, run, path=["response"]) @parametrize async def test_streaming_response_update(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.runs.with_streaming_response.update( run_id="run_id", thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() assert_matches_type(Run, run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_update(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.threads.runs.with_raw_response.update( run_id="run_id", thread_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): await async_client.beta.threads.runs.with_raw_response.update( run_id="", thread_id="thread_id", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): run = await async_client.beta.threads.runs.list( thread_id="thread_id", ) assert_matches_type(AsyncCursorPage[Run], run, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): run = await async_client.beta.threads.runs.list( thread_id="thread_id", after="after", before="before", limit=0, order="asc", ) assert_matches_type(AsyncCursorPage[Run], run, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.runs.with_raw_response.list( thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(AsyncCursorPage[Run], run, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.runs.with_streaming_response.list( thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() assert_matches_type(AsyncCursorPage[Run], run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_list(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.threads.runs.with_raw_response.list( thread_id="", ) @parametrize async def test_method_cancel(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): run = await async_client.beta.threads.runs.cancel( run_id="run_id", thread_id="thread_id", ) assert_matches_type(Run, run, path=["response"]) @parametrize async def test_raw_response_cancel(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.runs.with_raw_response.cancel( run_id="run_id", thread_id="thread_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(Run, run, path=["response"]) @parametrize async def test_streaming_response_cancel(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.runs.with_streaming_response.cancel( run_id="run_id", thread_id="thread_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() assert_matches_type(Run, run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_cancel(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.threads.runs.with_raw_response.cancel( run_id="run_id", thread_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): await async_client.beta.threads.runs.with_raw_response.cancel( run_id="", thread_id="thread_id", ) @parametrize async def test_method_submit_tool_outputs_overload_1(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): run = await async_client.beta.threads.runs.submit_tool_outputs( run_id="run_id", thread_id="thread_id", tool_outputs=[{}], ) assert_matches_type(Run, run, path=["response"]) @parametrize async def test_method_submit_tool_outputs_with_all_params_overload_1(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): run = await async_client.beta.threads.runs.submit_tool_outputs( run_id="run_id", thread_id="thread_id", tool_outputs=[ { "output": "output", "tool_call_id": "tool_call_id", } ], stream=False, ) assert_matches_type(Run, run, path=["response"]) @parametrize async def test_raw_response_submit_tool_outputs_overload_1(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.runs.with_raw_response.submit_tool_outputs( run_id="run_id", thread_id="thread_id", tool_outputs=[{}], ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(Run, run, path=["response"]) @parametrize async def test_streaming_response_submit_tool_outputs_overload_1(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.runs.with_streaming_response.submit_tool_outputs( run_id="run_id", thread_id="thread_id", tool_outputs=[{}], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() assert_matches_type(Run, run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_submit_tool_outputs_overload_1(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.threads.runs.with_raw_response.submit_tool_outputs( run_id="run_id", thread_id="", tool_outputs=[{}], ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): await async_client.beta.threads.runs.with_raw_response.submit_tool_outputs( run_id="", thread_id="thread_id", tool_outputs=[{}], ) @parametrize async def test_method_submit_tool_outputs_overload_2(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): run_stream = await async_client.beta.threads.runs.submit_tool_outputs( run_id="run_id", thread_id="thread_id", stream=True, tool_outputs=[{}], ) await run_stream.response.aclose() @parametrize async def test_raw_response_submit_tool_outputs_overload_2(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.beta.threads.runs.with_raw_response.submit_tool_outputs( run_id="run_id", thread_id="thread_id", stream=True, tool_outputs=[{}], ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() await stream.close() @parametrize async def test_streaming_response_submit_tool_outputs_overload_2(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.beta.threads.runs.with_streaming_response.submit_tool_outputs( run_id="run_id", thread_id="thread_id", stream=True, tool_outputs=[{}], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = await response.parse() await stream.close() assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_submit_tool_outputs_overload_2(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"): await async_client.beta.threads.runs.with_raw_response.submit_tool_outputs( run_id="run_id", thread_id="", stream=True, tool_outputs=[{}], ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): await async_client.beta.threads.runs.with_raw_response.submit_tool_outputs( run_id="", thread_id="thread_id", stream=True, tool_outputs=[{}], ) ================================================ FILE: tests/api_resources/chat/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/chat/completions/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/chat/completions/test_messages.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.pagination import SyncCursorPage, AsyncCursorPage from openai.types.chat import ChatCompletionStoreMessage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestMessages: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_list(self, client: OpenAI) -> None: message = client.chat.completions.messages.list( completion_id="completion_id", ) assert_matches_type(SyncCursorPage[ChatCompletionStoreMessage], message, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: message = client.chat.completions.messages.list( completion_id="completion_id", after="after", limit=0, order="asc", ) assert_matches_type(SyncCursorPage[ChatCompletionStoreMessage], message, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.chat.completions.messages.with_raw_response.list( completion_id="completion_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = response.parse() assert_matches_type(SyncCursorPage[ChatCompletionStoreMessage], message, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.chat.completions.messages.with_streaming_response.list( completion_id="completion_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = response.parse() assert_matches_type(SyncCursorPage[ChatCompletionStoreMessage], message, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_list(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `completion_id` but received ''"): client.chat.completions.messages.with_raw_response.list( completion_id="", ) class TestAsyncMessages: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: message = await async_client.chat.completions.messages.list( completion_id="completion_id", ) assert_matches_type(AsyncCursorPage[ChatCompletionStoreMessage], message, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: message = await async_client.chat.completions.messages.list( completion_id="completion_id", after="after", limit=0, order="asc", ) assert_matches_type(AsyncCursorPage[ChatCompletionStoreMessage], message, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.chat.completions.messages.with_raw_response.list( completion_id="completion_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = response.parse() assert_matches_type(AsyncCursorPage[ChatCompletionStoreMessage], message, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.chat.completions.messages.with_streaming_response.list( completion_id="completion_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" message = await response.parse() assert_matches_type(AsyncCursorPage[ChatCompletionStoreMessage], message, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_list(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `completion_id` but received ''"): await async_client.chat.completions.messages.with_raw_response.list( completion_id="", ) ================================================ FILE: tests/api_resources/chat/test_completions.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest import pydantic from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.pagination import SyncCursorPage, AsyncCursorPage from openai.types.chat import ( ChatCompletion, ChatCompletionDeleted, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestCompletions: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create_overload_1(self, client: OpenAI) -> None: completion = client.chat.completions.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", ) assert_matches_type(ChatCompletion, completion, path=["response"]) @parametrize def test_method_create_with_all_params_overload_1(self, client: OpenAI) -> None: completion = client.chat.completions.create( messages=[ { "content": "string", "role": "developer", "name": "name", } ], model="gpt-5.4", audio={ "format": "wav", "voice": "string", }, frequency_penalty=-2, function_call="none", functions=[ { "name": "name", "description": "description", "parameters": {"foo": "bar"}, } ], logit_bias={"foo": 0}, logprobs=True, max_completion_tokens=0, max_tokens=0, metadata={"foo": "string"}, modalities=["text"], n=1, parallel_tool_calls=True, prediction={ "content": "string", "type": "content", }, presence_penalty=-2, prompt_cache_key="prompt-cache-key-1234", prompt_cache_retention="in-memory", reasoning_effort="none", response_format={"type": "text"}, safety_identifier="safety-identifier-1234", seed=-9007199254740991, service_tier="auto", stop="\n", store=True, stream=False, stream_options={ "include_obfuscation": True, "include_usage": True, }, temperature=1, tool_choice="none", tools=[ { "function": { "name": "name", "description": "description", "parameters": {"foo": "bar"}, "strict": True, }, "type": "function", } ], top_logprobs=0, top_p=1, user="user-1234", verbosity="low", web_search_options={ "search_context_size": "low", "user_location": { "approximate": { "city": "city", "country": "country", "region": "region", "timezone": "timezone", }, "type": "approximate", }, }, ) assert_matches_type(ChatCompletion, completion, path=["response"]) @parametrize def test_raw_response_create_overload_1(self, client: OpenAI) -> None: response = client.chat.completions.with_raw_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = response.parse() assert_matches_type(ChatCompletion, completion, path=["response"]) @parametrize def test_streaming_response_create_overload_1(self, client: OpenAI) -> None: with client.chat.completions.with_streaming_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = response.parse() assert_matches_type(ChatCompletion, completion, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_create_overload_2(self, client: OpenAI) -> None: completion_stream = client.chat.completions.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", stream=True, ) completion_stream.response.close() @parametrize def test_method_create_with_all_params_overload_2(self, client: OpenAI) -> None: completion_stream = client.chat.completions.create( messages=[ { "content": "string", "role": "developer", "name": "name", } ], model="gpt-5.4", stream=True, audio={ "format": "wav", "voice": "string", }, frequency_penalty=-2, function_call="none", functions=[ { "name": "name", "description": "description", "parameters": {"foo": "bar"}, } ], logit_bias={"foo": 0}, logprobs=True, max_completion_tokens=0, max_tokens=0, metadata={"foo": "string"}, modalities=["text"], n=1, parallel_tool_calls=True, prediction={ "content": "string", "type": "content", }, presence_penalty=-2, prompt_cache_key="prompt-cache-key-1234", prompt_cache_retention="in-memory", reasoning_effort="none", response_format={"type": "text"}, safety_identifier="safety-identifier-1234", seed=-9007199254740991, service_tier="auto", stop="\n", store=True, stream_options={ "include_obfuscation": True, "include_usage": True, }, temperature=1, tool_choice="none", tools=[ { "function": { "name": "name", "description": "description", "parameters": {"foo": "bar"}, "strict": True, }, "type": "function", } ], top_logprobs=0, top_p=1, user="user-1234", verbosity="low", web_search_options={ "search_context_size": "low", "user_location": { "approximate": { "city": "city", "country": "country", "region": "region", "timezone": "timezone", }, "type": "approximate", }, }, ) completion_stream.response.close() @parametrize def test_raw_response_create_overload_2(self, client: OpenAI) -> None: response = client.chat.completions.with_raw_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", stream=True, ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() @parametrize def test_streaming_response_create_overload_2(self, client: OpenAI) -> None: with client.chat.completions.with_streaming_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", stream=True, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() assert cast(Any, response.is_closed) is True @parametrize def test_method_retrieve(self, client: OpenAI) -> None: completion = client.chat.completions.retrieve( "completion_id", ) assert_matches_type(ChatCompletion, completion, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: response = client.chat.completions.with_raw_response.retrieve( "completion_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = response.parse() assert_matches_type(ChatCompletion, completion, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with client.chat.completions.with_streaming_response.retrieve( "completion_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = response.parse() assert_matches_type(ChatCompletion, completion, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `completion_id` but received ''"): client.chat.completions.with_raw_response.retrieve( "", ) @parametrize def test_method_update(self, client: OpenAI) -> None: completion = client.chat.completions.update( completion_id="completion_id", metadata={"foo": "string"}, ) assert_matches_type(ChatCompletion, completion, path=["response"]) @parametrize def test_raw_response_update(self, client: OpenAI) -> None: response = client.chat.completions.with_raw_response.update( completion_id="completion_id", metadata={"foo": "string"}, ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = response.parse() assert_matches_type(ChatCompletion, completion, path=["response"]) @parametrize def test_streaming_response_update(self, client: OpenAI) -> None: with client.chat.completions.with_streaming_response.update( completion_id="completion_id", metadata={"foo": "string"}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = response.parse() assert_matches_type(ChatCompletion, completion, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_update(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `completion_id` but received ''"): client.chat.completions.with_raw_response.update( completion_id="", metadata={"foo": "string"}, ) @parametrize def test_method_list(self, client: OpenAI) -> None: completion = client.chat.completions.list() assert_matches_type(SyncCursorPage[ChatCompletion], completion, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: completion = client.chat.completions.list( after="after", limit=0, metadata={"foo": "string"}, model="model", order="asc", ) assert_matches_type(SyncCursorPage[ChatCompletion], completion, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.chat.completions.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = response.parse() assert_matches_type(SyncCursorPage[ChatCompletion], completion, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.chat.completions.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = response.parse() assert_matches_type(SyncCursorPage[ChatCompletion], completion, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_delete(self, client: OpenAI) -> None: completion = client.chat.completions.delete( "completion_id", ) assert_matches_type(ChatCompletionDeleted, completion, path=["response"]) @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: response = client.chat.completions.with_raw_response.delete( "completion_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = response.parse() assert_matches_type(ChatCompletionDeleted, completion, path=["response"]) @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with client.chat.completions.with_streaming_response.delete( "completion_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = response.parse() assert_matches_type(ChatCompletionDeleted, completion, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `completion_id` but received ''"): client.chat.completions.with_raw_response.delete( "", ) @parametrize def test_method_create_disallows_pydantic(self, client: OpenAI) -> None: class MyModel(pydantic.BaseModel): a: str with pytest.raises(TypeError, match=r"You tried to pass a `BaseModel` class"): client.chat.completions.create( messages=[ { "content": "string", "role": "system", } ], model="gpt-4o", response_format=cast(Any, MyModel), ) class TestAsyncCompletions: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create_overload_1(self, async_client: AsyncOpenAI) -> None: completion = await async_client.chat.completions.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", ) assert_matches_type(ChatCompletion, completion, path=["response"]) @parametrize async def test_method_create_with_all_params_overload_1(self, async_client: AsyncOpenAI) -> None: completion = await async_client.chat.completions.create( messages=[ { "content": "string", "role": "developer", "name": "name", } ], model="gpt-5.4", audio={ "format": "wav", "voice": "string", }, frequency_penalty=-2, function_call="none", functions=[ { "name": "name", "description": "description", "parameters": {"foo": "bar"}, } ], logit_bias={"foo": 0}, logprobs=True, max_completion_tokens=0, max_tokens=0, metadata={"foo": "string"}, modalities=["text"], n=1, parallel_tool_calls=True, prediction={ "content": "string", "type": "content", }, presence_penalty=-2, prompt_cache_key="prompt-cache-key-1234", prompt_cache_retention="in-memory", reasoning_effort="none", response_format={"type": "text"}, safety_identifier="safety-identifier-1234", seed=-9007199254740991, service_tier="auto", stop="\n", store=True, stream=False, stream_options={ "include_obfuscation": True, "include_usage": True, }, temperature=1, tool_choice="none", tools=[ { "function": { "name": "name", "description": "description", "parameters": {"foo": "bar"}, "strict": True, }, "type": "function", } ], top_logprobs=0, top_p=1, user="user-1234", verbosity="low", web_search_options={ "search_context_size": "low", "user_location": { "approximate": { "city": "city", "country": "country", "region": "region", "timezone": "timezone", }, "type": "approximate", }, }, ) assert_matches_type(ChatCompletion, completion, path=["response"]) @parametrize async def test_raw_response_create_overload_1(self, async_client: AsyncOpenAI) -> None: response = await async_client.chat.completions.with_raw_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = response.parse() assert_matches_type(ChatCompletion, completion, path=["response"]) @parametrize async def test_streaming_response_create_overload_1(self, async_client: AsyncOpenAI) -> None: async with async_client.chat.completions.with_streaming_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = await response.parse() assert_matches_type(ChatCompletion, completion, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_create_overload_2(self, async_client: AsyncOpenAI) -> None: completion_stream = await async_client.chat.completions.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", stream=True, ) await completion_stream.response.aclose() @parametrize async def test_method_create_with_all_params_overload_2(self, async_client: AsyncOpenAI) -> None: completion_stream = await async_client.chat.completions.create( messages=[ { "content": "string", "role": "developer", "name": "name", } ], model="gpt-5.4", stream=True, audio={ "format": "wav", "voice": "string", }, frequency_penalty=-2, function_call="none", functions=[ { "name": "name", "description": "description", "parameters": {"foo": "bar"}, } ], logit_bias={"foo": 0}, logprobs=True, max_completion_tokens=0, max_tokens=0, metadata={"foo": "string"}, modalities=["text"], n=1, parallel_tool_calls=True, prediction={ "content": "string", "type": "content", }, presence_penalty=-2, prompt_cache_key="prompt-cache-key-1234", prompt_cache_retention="in-memory", reasoning_effort="none", response_format={"type": "text"}, safety_identifier="safety-identifier-1234", seed=-9007199254740991, service_tier="auto", stop="\n", store=True, stream_options={ "include_obfuscation": True, "include_usage": True, }, temperature=1, tool_choice="none", tools=[ { "function": { "name": "name", "description": "description", "parameters": {"foo": "bar"}, "strict": True, }, "type": "function", } ], top_logprobs=0, top_p=1, user="user-1234", verbosity="low", web_search_options={ "search_context_size": "low", "user_location": { "approximate": { "city": "city", "country": "country", "region": "region", "timezone": "timezone", }, "type": "approximate", }, }, ) await completion_stream.response.aclose() @parametrize async def test_raw_response_create_overload_2(self, async_client: AsyncOpenAI) -> None: response = await async_client.chat.completions.with_raw_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", stream=True, ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() await stream.close() @parametrize async def test_streaming_response_create_overload_2(self, async_client: AsyncOpenAI) -> None: async with async_client.chat.completions.with_streaming_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", stream=True, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = await response.parse() await stream.close() assert cast(Any, response.is_closed) is True @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: completion = await async_client.chat.completions.retrieve( "completion_id", ) assert_matches_type(ChatCompletion, completion, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: response = await async_client.chat.completions.with_raw_response.retrieve( "completion_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = response.parse() assert_matches_type(ChatCompletion, completion, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: async with async_client.chat.completions.with_streaming_response.retrieve( "completion_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = await response.parse() assert_matches_type(ChatCompletion, completion, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `completion_id` but received ''"): await async_client.chat.completions.with_raw_response.retrieve( "", ) @parametrize async def test_method_update(self, async_client: AsyncOpenAI) -> None: completion = await async_client.chat.completions.update( completion_id="completion_id", metadata={"foo": "string"}, ) assert_matches_type(ChatCompletion, completion, path=["response"]) @parametrize async def test_raw_response_update(self, async_client: AsyncOpenAI) -> None: response = await async_client.chat.completions.with_raw_response.update( completion_id="completion_id", metadata={"foo": "string"}, ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = response.parse() assert_matches_type(ChatCompletion, completion, path=["response"]) @parametrize async def test_streaming_response_update(self, async_client: AsyncOpenAI) -> None: async with async_client.chat.completions.with_streaming_response.update( completion_id="completion_id", metadata={"foo": "string"}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = await response.parse() assert_matches_type(ChatCompletion, completion, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_update(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `completion_id` but received ''"): await async_client.chat.completions.with_raw_response.update( completion_id="", metadata={"foo": "string"}, ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: completion = await async_client.chat.completions.list() assert_matches_type(AsyncCursorPage[ChatCompletion], completion, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: completion = await async_client.chat.completions.list( after="after", limit=0, metadata={"foo": "string"}, model="model", order="asc", ) assert_matches_type(AsyncCursorPage[ChatCompletion], completion, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.chat.completions.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = response.parse() assert_matches_type(AsyncCursorPage[ChatCompletion], completion, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.chat.completions.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = await response.parse() assert_matches_type(AsyncCursorPage[ChatCompletion], completion, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: completion = await async_client.chat.completions.delete( "completion_id", ) assert_matches_type(ChatCompletionDeleted, completion, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: response = await async_client.chat.completions.with_raw_response.delete( "completion_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = response.parse() assert_matches_type(ChatCompletionDeleted, completion, path=["response"]) @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: async with async_client.chat.completions.with_streaming_response.delete( "completion_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = await response.parse() assert_matches_type(ChatCompletionDeleted, completion, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `completion_id` but received ''"): await async_client.chat.completions.with_raw_response.delete( "", ) @parametrize async def test_method_create_disallows_pydantic(self, async_client: AsyncOpenAI) -> None: class MyModel(pydantic.BaseModel): a: str with pytest.raises(TypeError, match=r"You tried to pass a `BaseModel` class"): await async_client.chat.completions.create( messages=[ { "content": "string", "role": "system", } ], model="gpt-4o", response_format=cast(Any, MyModel), ) ================================================ FILE: tests/api_resources/containers/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/containers/files/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/containers/files/test_content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import httpx import pytest from respx import MockRouter import openai._legacy_response as _legacy_response from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type # pyright: reportDeprecated=false base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestContent: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize @pytest.mark.respx(base_url=base_url) def test_method_retrieve(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/containers/container_id/files/file_id/content").mock( return_value=httpx.Response(200, json={"foo": "bar"}) ) content = client.containers.files.content.retrieve( file_id="file_id", container_id="container_id", ) assert isinstance(content, _legacy_response.HttpxBinaryResponseContent) assert content.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) def test_raw_response_retrieve(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/containers/container_id/files/file_id/content").mock( return_value=httpx.Response(200, json={"foo": "bar"}) ) response = client.containers.files.content.with_raw_response.retrieve( file_id="file_id", container_id="container_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" content = response.parse() assert_matches_type(_legacy_response.HttpxBinaryResponseContent, content, path=["response"]) @parametrize @pytest.mark.respx(base_url=base_url) def test_streaming_response_retrieve(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/containers/container_id/files/file_id/content").mock( return_value=httpx.Response(200, json={"foo": "bar"}) ) with client.containers.files.content.with_streaming_response.retrieve( file_id="file_id", container_id="container_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" content = response.parse() assert_matches_type(bytes, content, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize @pytest.mark.respx(base_url=base_url) def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `container_id` but received ''"): client.containers.files.content.with_raw_response.retrieve( file_id="file_id", container_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): client.containers.files.content.with_raw_response.retrieve( file_id="", container_id="container_id", ) class TestAsyncContent: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize @pytest.mark.respx(base_url=base_url) async def test_method_retrieve(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/containers/container_id/files/file_id/content").mock( return_value=httpx.Response(200, json={"foo": "bar"}) ) content = await async_client.containers.files.content.retrieve( file_id="file_id", container_id="container_id", ) assert isinstance(content, _legacy_response.HttpxBinaryResponseContent) assert content.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) async def test_raw_response_retrieve(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/containers/container_id/files/file_id/content").mock( return_value=httpx.Response(200, json={"foo": "bar"}) ) response = await async_client.containers.files.content.with_raw_response.retrieve( file_id="file_id", container_id="container_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" content = response.parse() assert_matches_type(_legacy_response.HttpxBinaryResponseContent, content, path=["response"]) @parametrize @pytest.mark.respx(base_url=base_url) async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/containers/container_id/files/file_id/content").mock( return_value=httpx.Response(200, json={"foo": "bar"}) ) async with async_client.containers.files.content.with_streaming_response.retrieve( file_id="file_id", container_id="container_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" content = await response.parse() assert_matches_type(bytes, content, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize @pytest.mark.respx(base_url=base_url) async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `container_id` but received ''"): await async_client.containers.files.content.with_raw_response.retrieve( file_id="file_id", container_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): await async_client.containers.files.content.with_raw_response.retrieve( file_id="", container_id="container_id", ) ================================================ FILE: tests/api_resources/containers/test_files.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.pagination import SyncCursorPage, AsyncCursorPage from openai.types.containers import ( FileListResponse, FileCreateResponse, FileRetrieveResponse, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestFiles: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: file = client.containers.files.create( container_id="container_id", ) assert_matches_type(FileCreateResponse, file, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: file = client.containers.files.create( container_id="container_id", file=b"Example data", file_id="file_id", ) assert_matches_type(FileCreateResponse, file, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.containers.files.with_raw_response.create( container_id="container_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(FileCreateResponse, file, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.containers.files.with_streaming_response.create( container_id="container_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(FileCreateResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_create(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `container_id` but received ''"): client.containers.files.with_raw_response.create( container_id="", ) @parametrize def test_method_retrieve(self, client: OpenAI) -> None: file = client.containers.files.retrieve( file_id="file_id", container_id="container_id", ) assert_matches_type(FileRetrieveResponse, file, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: response = client.containers.files.with_raw_response.retrieve( file_id="file_id", container_id="container_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(FileRetrieveResponse, file, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with client.containers.files.with_streaming_response.retrieve( file_id="file_id", container_id="container_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(FileRetrieveResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `container_id` but received ''"): client.containers.files.with_raw_response.retrieve( file_id="file_id", container_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): client.containers.files.with_raw_response.retrieve( file_id="", container_id="container_id", ) @parametrize def test_method_list(self, client: OpenAI) -> None: file = client.containers.files.list( container_id="container_id", ) assert_matches_type(SyncCursorPage[FileListResponse], file, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: file = client.containers.files.list( container_id="container_id", after="after", limit=0, order="asc", ) assert_matches_type(SyncCursorPage[FileListResponse], file, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.containers.files.with_raw_response.list( container_id="container_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(SyncCursorPage[FileListResponse], file, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.containers.files.with_streaming_response.list( container_id="container_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(SyncCursorPage[FileListResponse], file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_list(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `container_id` but received ''"): client.containers.files.with_raw_response.list( container_id="", ) @parametrize def test_method_delete(self, client: OpenAI) -> None: file = client.containers.files.delete( file_id="file_id", container_id="container_id", ) assert file is None @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: response = client.containers.files.with_raw_response.delete( file_id="file_id", container_id="container_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert file is None @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with client.containers.files.with_streaming_response.delete( file_id="file_id", container_id="container_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert file is None assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `container_id` but received ''"): client.containers.files.with_raw_response.delete( file_id="file_id", container_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): client.containers.files.with_raw_response.delete( file_id="", container_id="container_id", ) class TestAsyncFiles: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: file = await async_client.containers.files.create( container_id="container_id", ) assert_matches_type(FileCreateResponse, file, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: file = await async_client.containers.files.create( container_id="container_id", file=b"Example data", file_id="file_id", ) assert_matches_type(FileCreateResponse, file, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.containers.files.with_raw_response.create( container_id="container_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(FileCreateResponse, file, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.containers.files.with_streaming_response.create( container_id="container_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() assert_matches_type(FileCreateResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_create(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `container_id` but received ''"): await async_client.containers.files.with_raw_response.create( container_id="", ) @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: file = await async_client.containers.files.retrieve( file_id="file_id", container_id="container_id", ) assert_matches_type(FileRetrieveResponse, file, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: response = await async_client.containers.files.with_raw_response.retrieve( file_id="file_id", container_id="container_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(FileRetrieveResponse, file, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: async with async_client.containers.files.with_streaming_response.retrieve( file_id="file_id", container_id="container_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() assert_matches_type(FileRetrieveResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `container_id` but received ''"): await async_client.containers.files.with_raw_response.retrieve( file_id="file_id", container_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): await async_client.containers.files.with_raw_response.retrieve( file_id="", container_id="container_id", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: file = await async_client.containers.files.list( container_id="container_id", ) assert_matches_type(AsyncCursorPage[FileListResponse], file, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: file = await async_client.containers.files.list( container_id="container_id", after="after", limit=0, order="asc", ) assert_matches_type(AsyncCursorPage[FileListResponse], file, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.containers.files.with_raw_response.list( container_id="container_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(AsyncCursorPage[FileListResponse], file, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.containers.files.with_streaming_response.list( container_id="container_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() assert_matches_type(AsyncCursorPage[FileListResponse], file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_list(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `container_id` but received ''"): await async_client.containers.files.with_raw_response.list( container_id="", ) @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: file = await async_client.containers.files.delete( file_id="file_id", container_id="container_id", ) assert file is None @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: response = await async_client.containers.files.with_raw_response.delete( file_id="file_id", container_id="container_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert file is None @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: async with async_client.containers.files.with_streaming_response.delete( file_id="file_id", container_id="container_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() assert file is None assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `container_id` but received ''"): await async_client.containers.files.with_raw_response.delete( file_id="file_id", container_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): await async_client.containers.files.with_raw_response.delete( file_id="", container_id="container_id", ) ================================================ FILE: tests/api_resources/conversations/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/conversations/test_items.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.pagination import SyncConversationCursorPage, AsyncConversationCursorPage from openai.types.conversations import ( Conversation, ConversationItem, ConversationItemList, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestItems: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: item = client.conversations.items.create( conversation_id="conv_123", items=[ { "content": "string", "role": "user", "type": "message", } ], ) assert_matches_type(ConversationItemList, item, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: item = client.conversations.items.create( conversation_id="conv_123", items=[ { "content": "string", "role": "user", "phase": "commentary", "type": "message", } ], include=["file_search_call.results"], ) assert_matches_type(ConversationItemList, item, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.conversations.items.with_raw_response.create( conversation_id="conv_123", items=[ { "content": "string", "role": "user", "type": "message", } ], ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" item = response.parse() assert_matches_type(ConversationItemList, item, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.conversations.items.with_streaming_response.create( conversation_id="conv_123", items=[ { "content": "string", "role": "user", "type": "message", } ], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" item = response.parse() assert_matches_type(ConversationItemList, item, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_create(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): client.conversations.items.with_raw_response.create( conversation_id="", items=[ { "content": "string", "role": "user", "type": "message", } ], ) @parametrize def test_method_retrieve(self, client: OpenAI) -> None: item = client.conversations.items.retrieve( item_id="msg_abc", conversation_id="conv_123", ) assert_matches_type(ConversationItem, item, path=["response"]) @parametrize def test_method_retrieve_with_all_params(self, client: OpenAI) -> None: item = client.conversations.items.retrieve( item_id="msg_abc", conversation_id="conv_123", include=["file_search_call.results"], ) assert_matches_type(ConversationItem, item, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: response = client.conversations.items.with_raw_response.retrieve( item_id="msg_abc", conversation_id="conv_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" item = response.parse() assert_matches_type(ConversationItem, item, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with client.conversations.items.with_streaming_response.retrieve( item_id="msg_abc", conversation_id="conv_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" item = response.parse() assert_matches_type(ConversationItem, item, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): client.conversations.items.with_raw_response.retrieve( item_id="msg_abc", conversation_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `item_id` but received ''"): client.conversations.items.with_raw_response.retrieve( item_id="", conversation_id="conv_123", ) @parametrize def test_method_list(self, client: OpenAI) -> None: item = client.conversations.items.list( conversation_id="conv_123", ) assert_matches_type(SyncConversationCursorPage[ConversationItem], item, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: item = client.conversations.items.list( conversation_id="conv_123", after="after", include=["file_search_call.results"], limit=0, order="asc", ) assert_matches_type(SyncConversationCursorPage[ConversationItem], item, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.conversations.items.with_raw_response.list( conversation_id="conv_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" item = response.parse() assert_matches_type(SyncConversationCursorPage[ConversationItem], item, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.conversations.items.with_streaming_response.list( conversation_id="conv_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" item = response.parse() assert_matches_type(SyncConversationCursorPage[ConversationItem], item, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_list(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): client.conversations.items.with_raw_response.list( conversation_id="", ) @parametrize def test_method_delete(self, client: OpenAI) -> None: item = client.conversations.items.delete( item_id="msg_abc", conversation_id="conv_123", ) assert_matches_type(Conversation, item, path=["response"]) @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: response = client.conversations.items.with_raw_response.delete( item_id="msg_abc", conversation_id="conv_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" item = response.parse() assert_matches_type(Conversation, item, path=["response"]) @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with client.conversations.items.with_streaming_response.delete( item_id="msg_abc", conversation_id="conv_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" item = response.parse() assert_matches_type(Conversation, item, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): client.conversations.items.with_raw_response.delete( item_id="msg_abc", conversation_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `item_id` but received ''"): client.conversations.items.with_raw_response.delete( item_id="", conversation_id="conv_123", ) class TestAsyncItems: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: item = await async_client.conversations.items.create( conversation_id="conv_123", items=[ { "content": "string", "role": "user", "type": "message", } ], ) assert_matches_type(ConversationItemList, item, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: item = await async_client.conversations.items.create( conversation_id="conv_123", items=[ { "content": "string", "role": "user", "phase": "commentary", "type": "message", } ], include=["file_search_call.results"], ) assert_matches_type(ConversationItemList, item, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.conversations.items.with_raw_response.create( conversation_id="conv_123", items=[ { "content": "string", "role": "user", "type": "message", } ], ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" item = response.parse() assert_matches_type(ConversationItemList, item, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.conversations.items.with_streaming_response.create( conversation_id="conv_123", items=[ { "content": "string", "role": "user", "type": "message", } ], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" item = await response.parse() assert_matches_type(ConversationItemList, item, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_create(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): await async_client.conversations.items.with_raw_response.create( conversation_id="", items=[ { "content": "string", "role": "user", "type": "message", } ], ) @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: item = await async_client.conversations.items.retrieve( item_id="msg_abc", conversation_id="conv_123", ) assert_matches_type(ConversationItem, item, path=["response"]) @parametrize async def test_method_retrieve_with_all_params(self, async_client: AsyncOpenAI) -> None: item = await async_client.conversations.items.retrieve( item_id="msg_abc", conversation_id="conv_123", include=["file_search_call.results"], ) assert_matches_type(ConversationItem, item, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: response = await async_client.conversations.items.with_raw_response.retrieve( item_id="msg_abc", conversation_id="conv_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" item = response.parse() assert_matches_type(ConversationItem, item, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: async with async_client.conversations.items.with_streaming_response.retrieve( item_id="msg_abc", conversation_id="conv_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" item = await response.parse() assert_matches_type(ConversationItem, item, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): await async_client.conversations.items.with_raw_response.retrieve( item_id="msg_abc", conversation_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `item_id` but received ''"): await async_client.conversations.items.with_raw_response.retrieve( item_id="", conversation_id="conv_123", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: item = await async_client.conversations.items.list( conversation_id="conv_123", ) assert_matches_type(AsyncConversationCursorPage[ConversationItem], item, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: item = await async_client.conversations.items.list( conversation_id="conv_123", after="after", include=["file_search_call.results"], limit=0, order="asc", ) assert_matches_type(AsyncConversationCursorPage[ConversationItem], item, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.conversations.items.with_raw_response.list( conversation_id="conv_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" item = response.parse() assert_matches_type(AsyncConversationCursorPage[ConversationItem], item, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.conversations.items.with_streaming_response.list( conversation_id="conv_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" item = await response.parse() assert_matches_type(AsyncConversationCursorPage[ConversationItem], item, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_list(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): await async_client.conversations.items.with_raw_response.list( conversation_id="", ) @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: item = await async_client.conversations.items.delete( item_id="msg_abc", conversation_id="conv_123", ) assert_matches_type(Conversation, item, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: response = await async_client.conversations.items.with_raw_response.delete( item_id="msg_abc", conversation_id="conv_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" item = response.parse() assert_matches_type(Conversation, item, path=["response"]) @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: async with async_client.conversations.items.with_streaming_response.delete( item_id="msg_abc", conversation_id="conv_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" item = await response.parse() assert_matches_type(Conversation, item, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): await async_client.conversations.items.with_raw_response.delete( item_id="msg_abc", conversation_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `item_id` but received ''"): await async_client.conversations.items.with_raw_response.delete( item_id="", conversation_id="conv_123", ) ================================================ FILE: tests/api_resources/evals/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/evals/runs/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/evals/runs/test_output_items.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.pagination import SyncCursorPage, AsyncCursorPage from openai.types.evals.runs import OutputItemListResponse, OutputItemRetrieveResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestOutputItems: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_retrieve(self, client: OpenAI) -> None: output_item = client.evals.runs.output_items.retrieve( output_item_id="output_item_id", eval_id="eval_id", run_id="run_id", ) assert_matches_type(OutputItemRetrieveResponse, output_item, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: response = client.evals.runs.output_items.with_raw_response.retrieve( output_item_id="output_item_id", eval_id="eval_id", run_id="run_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" output_item = response.parse() assert_matches_type(OutputItemRetrieveResponse, output_item, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with client.evals.runs.output_items.with_streaming_response.retrieve( output_item_id="output_item_id", eval_id="eval_id", run_id="run_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" output_item = response.parse() assert_matches_type(OutputItemRetrieveResponse, output_item, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): client.evals.runs.output_items.with_raw_response.retrieve( output_item_id="output_item_id", eval_id="", run_id="run_id", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): client.evals.runs.output_items.with_raw_response.retrieve( output_item_id="output_item_id", eval_id="eval_id", run_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `output_item_id` but received ''"): client.evals.runs.output_items.with_raw_response.retrieve( output_item_id="", eval_id="eval_id", run_id="run_id", ) @parametrize def test_method_list(self, client: OpenAI) -> None: output_item = client.evals.runs.output_items.list( run_id="run_id", eval_id="eval_id", ) assert_matches_type(SyncCursorPage[OutputItemListResponse], output_item, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: output_item = client.evals.runs.output_items.list( run_id="run_id", eval_id="eval_id", after="after", limit=0, order="asc", status="fail", ) assert_matches_type(SyncCursorPage[OutputItemListResponse], output_item, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.evals.runs.output_items.with_raw_response.list( run_id="run_id", eval_id="eval_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" output_item = response.parse() assert_matches_type(SyncCursorPage[OutputItemListResponse], output_item, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.evals.runs.output_items.with_streaming_response.list( run_id="run_id", eval_id="eval_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" output_item = response.parse() assert_matches_type(SyncCursorPage[OutputItemListResponse], output_item, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_list(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): client.evals.runs.output_items.with_raw_response.list( run_id="run_id", eval_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): client.evals.runs.output_items.with_raw_response.list( run_id="", eval_id="eval_id", ) class TestAsyncOutputItems: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: output_item = await async_client.evals.runs.output_items.retrieve( output_item_id="output_item_id", eval_id="eval_id", run_id="run_id", ) assert_matches_type(OutputItemRetrieveResponse, output_item, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: response = await async_client.evals.runs.output_items.with_raw_response.retrieve( output_item_id="output_item_id", eval_id="eval_id", run_id="run_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" output_item = response.parse() assert_matches_type(OutputItemRetrieveResponse, output_item, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: async with async_client.evals.runs.output_items.with_streaming_response.retrieve( output_item_id="output_item_id", eval_id="eval_id", run_id="run_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" output_item = await response.parse() assert_matches_type(OutputItemRetrieveResponse, output_item, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): await async_client.evals.runs.output_items.with_raw_response.retrieve( output_item_id="output_item_id", eval_id="", run_id="run_id", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): await async_client.evals.runs.output_items.with_raw_response.retrieve( output_item_id="output_item_id", eval_id="eval_id", run_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `output_item_id` but received ''"): await async_client.evals.runs.output_items.with_raw_response.retrieve( output_item_id="", eval_id="eval_id", run_id="run_id", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: output_item = await async_client.evals.runs.output_items.list( run_id="run_id", eval_id="eval_id", ) assert_matches_type(AsyncCursorPage[OutputItemListResponse], output_item, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: output_item = await async_client.evals.runs.output_items.list( run_id="run_id", eval_id="eval_id", after="after", limit=0, order="asc", status="fail", ) assert_matches_type(AsyncCursorPage[OutputItemListResponse], output_item, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.evals.runs.output_items.with_raw_response.list( run_id="run_id", eval_id="eval_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" output_item = response.parse() assert_matches_type(AsyncCursorPage[OutputItemListResponse], output_item, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.evals.runs.output_items.with_streaming_response.list( run_id="run_id", eval_id="eval_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" output_item = await response.parse() assert_matches_type(AsyncCursorPage[OutputItemListResponse], output_item, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_list(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): await async_client.evals.runs.output_items.with_raw_response.list( run_id="run_id", eval_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): await async_client.evals.runs.output_items.with_raw_response.list( run_id="", eval_id="eval_id", ) ================================================ FILE: tests/api_resources/evals/test_runs.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.pagination import SyncCursorPage, AsyncCursorPage from openai.types.evals import ( RunListResponse, RunCancelResponse, RunCreateResponse, RunDeleteResponse, RunRetrieveResponse, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestRuns: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: run = client.evals.runs.create( eval_id="eval_id", data_source={ "source": { "content": [{"item": {"foo": "bar"}}], "type": "file_content", }, "type": "jsonl", }, ) assert_matches_type(RunCreateResponse, run, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: run = client.evals.runs.create( eval_id="eval_id", data_source={ "source": { "content": [ { "item": {"foo": "bar"}, "sample": {"foo": "bar"}, } ], "type": "file_content", }, "type": "jsonl", }, metadata={"foo": "string"}, name="name", ) assert_matches_type(RunCreateResponse, run, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.evals.runs.with_raw_response.create( eval_id="eval_id", data_source={ "source": { "content": [{"item": {"foo": "bar"}}], "type": "file_content", }, "type": "jsonl", }, ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(RunCreateResponse, run, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.evals.runs.with_streaming_response.create( eval_id="eval_id", data_source={ "source": { "content": [{"item": {"foo": "bar"}}], "type": "file_content", }, "type": "jsonl", }, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(RunCreateResponse, run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_create(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): client.evals.runs.with_raw_response.create( eval_id="", data_source={ "source": { "content": [{"item": {"foo": "bar"}}], "type": "file_content", }, "type": "jsonl", }, ) @parametrize def test_method_retrieve(self, client: OpenAI) -> None: run = client.evals.runs.retrieve( run_id="run_id", eval_id="eval_id", ) assert_matches_type(RunRetrieveResponse, run, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: response = client.evals.runs.with_raw_response.retrieve( run_id="run_id", eval_id="eval_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(RunRetrieveResponse, run, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with client.evals.runs.with_streaming_response.retrieve( run_id="run_id", eval_id="eval_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(RunRetrieveResponse, run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): client.evals.runs.with_raw_response.retrieve( run_id="run_id", eval_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): client.evals.runs.with_raw_response.retrieve( run_id="", eval_id="eval_id", ) @parametrize def test_method_list(self, client: OpenAI) -> None: run = client.evals.runs.list( eval_id="eval_id", ) assert_matches_type(SyncCursorPage[RunListResponse], run, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: run = client.evals.runs.list( eval_id="eval_id", after="after", limit=0, order="asc", status="queued", ) assert_matches_type(SyncCursorPage[RunListResponse], run, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.evals.runs.with_raw_response.list( eval_id="eval_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(SyncCursorPage[RunListResponse], run, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.evals.runs.with_streaming_response.list( eval_id="eval_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(SyncCursorPage[RunListResponse], run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_list(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): client.evals.runs.with_raw_response.list( eval_id="", ) @parametrize def test_method_delete(self, client: OpenAI) -> None: run = client.evals.runs.delete( run_id="run_id", eval_id="eval_id", ) assert_matches_type(RunDeleteResponse, run, path=["response"]) @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: response = client.evals.runs.with_raw_response.delete( run_id="run_id", eval_id="eval_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(RunDeleteResponse, run, path=["response"]) @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with client.evals.runs.with_streaming_response.delete( run_id="run_id", eval_id="eval_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(RunDeleteResponse, run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): client.evals.runs.with_raw_response.delete( run_id="run_id", eval_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): client.evals.runs.with_raw_response.delete( run_id="", eval_id="eval_id", ) @parametrize def test_method_cancel(self, client: OpenAI) -> None: run = client.evals.runs.cancel( run_id="run_id", eval_id="eval_id", ) assert_matches_type(RunCancelResponse, run, path=["response"]) @parametrize def test_raw_response_cancel(self, client: OpenAI) -> None: response = client.evals.runs.with_raw_response.cancel( run_id="run_id", eval_id="eval_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(RunCancelResponse, run, path=["response"]) @parametrize def test_streaming_response_cancel(self, client: OpenAI) -> None: with client.evals.runs.with_streaming_response.cancel( run_id="run_id", eval_id="eval_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(RunCancelResponse, run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_cancel(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): client.evals.runs.with_raw_response.cancel( run_id="run_id", eval_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): client.evals.runs.with_raw_response.cancel( run_id="", eval_id="eval_id", ) class TestAsyncRuns: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: run = await async_client.evals.runs.create( eval_id="eval_id", data_source={ "source": { "content": [{"item": {"foo": "bar"}}], "type": "file_content", }, "type": "jsonl", }, ) assert_matches_type(RunCreateResponse, run, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: run = await async_client.evals.runs.create( eval_id="eval_id", data_source={ "source": { "content": [ { "item": {"foo": "bar"}, "sample": {"foo": "bar"}, } ], "type": "file_content", }, "type": "jsonl", }, metadata={"foo": "string"}, name="name", ) assert_matches_type(RunCreateResponse, run, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.evals.runs.with_raw_response.create( eval_id="eval_id", data_source={ "source": { "content": [{"item": {"foo": "bar"}}], "type": "file_content", }, "type": "jsonl", }, ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(RunCreateResponse, run, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.evals.runs.with_streaming_response.create( eval_id="eval_id", data_source={ "source": { "content": [{"item": {"foo": "bar"}}], "type": "file_content", }, "type": "jsonl", }, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() assert_matches_type(RunCreateResponse, run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_create(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): await async_client.evals.runs.with_raw_response.create( eval_id="", data_source={ "source": { "content": [{"item": {"foo": "bar"}}], "type": "file_content", }, "type": "jsonl", }, ) @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: run = await async_client.evals.runs.retrieve( run_id="run_id", eval_id="eval_id", ) assert_matches_type(RunRetrieveResponse, run, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: response = await async_client.evals.runs.with_raw_response.retrieve( run_id="run_id", eval_id="eval_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(RunRetrieveResponse, run, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: async with async_client.evals.runs.with_streaming_response.retrieve( run_id="run_id", eval_id="eval_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() assert_matches_type(RunRetrieveResponse, run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): await async_client.evals.runs.with_raw_response.retrieve( run_id="run_id", eval_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): await async_client.evals.runs.with_raw_response.retrieve( run_id="", eval_id="eval_id", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: run = await async_client.evals.runs.list( eval_id="eval_id", ) assert_matches_type(AsyncCursorPage[RunListResponse], run, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: run = await async_client.evals.runs.list( eval_id="eval_id", after="after", limit=0, order="asc", status="queued", ) assert_matches_type(AsyncCursorPage[RunListResponse], run, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.evals.runs.with_raw_response.list( eval_id="eval_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(AsyncCursorPage[RunListResponse], run, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.evals.runs.with_streaming_response.list( eval_id="eval_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() assert_matches_type(AsyncCursorPage[RunListResponse], run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_list(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): await async_client.evals.runs.with_raw_response.list( eval_id="", ) @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: run = await async_client.evals.runs.delete( run_id="run_id", eval_id="eval_id", ) assert_matches_type(RunDeleteResponse, run, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: response = await async_client.evals.runs.with_raw_response.delete( run_id="run_id", eval_id="eval_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(RunDeleteResponse, run, path=["response"]) @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: async with async_client.evals.runs.with_streaming_response.delete( run_id="run_id", eval_id="eval_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() assert_matches_type(RunDeleteResponse, run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): await async_client.evals.runs.with_raw_response.delete( run_id="run_id", eval_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): await async_client.evals.runs.with_raw_response.delete( run_id="", eval_id="eval_id", ) @parametrize async def test_method_cancel(self, async_client: AsyncOpenAI) -> None: run = await async_client.evals.runs.cancel( run_id="run_id", eval_id="eval_id", ) assert_matches_type(RunCancelResponse, run, path=["response"]) @parametrize async def test_raw_response_cancel(self, async_client: AsyncOpenAI) -> None: response = await async_client.evals.runs.with_raw_response.cancel( run_id="run_id", eval_id="eval_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = response.parse() assert_matches_type(RunCancelResponse, run, path=["response"]) @parametrize async def test_streaming_response_cancel(self, async_client: AsyncOpenAI) -> None: async with async_client.evals.runs.with_streaming_response.cancel( run_id="run_id", eval_id="eval_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" run = await response.parse() assert_matches_type(RunCancelResponse, run, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_cancel(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): await async_client.evals.runs.with_raw_response.cancel( run_id="run_id", eval_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): await async_client.evals.runs.with_raw_response.cancel( run_id="", eval_id="eval_id", ) ================================================ FILE: tests/api_resources/fine_tuning/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/fine_tuning/alpha/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/fine_tuning/alpha/test_graders.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types.fine_tuning.alpha import ( GraderRunResponse, GraderValidateResponse, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestGraders: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_run(self, client: OpenAI) -> None: grader = client.fine_tuning.alpha.graders.run( grader={ "input": "input", "name": "name", "operation": "eq", "reference": "reference", "type": "string_check", }, model_sample="model_sample", ) assert_matches_type(GraderRunResponse, grader, path=["response"]) @parametrize def test_method_run_with_all_params(self, client: OpenAI) -> None: grader = client.fine_tuning.alpha.graders.run( grader={ "input": "input", "name": "name", "operation": "eq", "reference": "reference", "type": "string_check", }, model_sample="model_sample", item={}, ) assert_matches_type(GraderRunResponse, grader, path=["response"]) @parametrize def test_raw_response_run(self, client: OpenAI) -> None: response = client.fine_tuning.alpha.graders.with_raw_response.run( grader={ "input": "input", "name": "name", "operation": "eq", "reference": "reference", "type": "string_check", }, model_sample="model_sample", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" grader = response.parse() assert_matches_type(GraderRunResponse, grader, path=["response"]) @parametrize def test_streaming_response_run(self, client: OpenAI) -> None: with client.fine_tuning.alpha.graders.with_streaming_response.run( grader={ "input": "input", "name": "name", "operation": "eq", "reference": "reference", "type": "string_check", }, model_sample="model_sample", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" grader = response.parse() assert_matches_type(GraderRunResponse, grader, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_validate(self, client: OpenAI) -> None: grader = client.fine_tuning.alpha.graders.validate( grader={ "input": "input", "name": "name", "operation": "eq", "reference": "reference", "type": "string_check", }, ) assert_matches_type(GraderValidateResponse, grader, path=["response"]) @parametrize def test_method_validate_with_all_params(self, client: OpenAI) -> None: grader = client.fine_tuning.alpha.graders.validate( grader={ "input": "input", "name": "name", "operation": "eq", "reference": "reference", "type": "string_check", }, ) assert_matches_type(GraderValidateResponse, grader, path=["response"]) @parametrize def test_raw_response_validate(self, client: OpenAI) -> None: response = client.fine_tuning.alpha.graders.with_raw_response.validate( grader={ "input": "input", "name": "name", "operation": "eq", "reference": "reference", "type": "string_check", }, ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" grader = response.parse() assert_matches_type(GraderValidateResponse, grader, path=["response"]) @parametrize def test_streaming_response_validate(self, client: OpenAI) -> None: with client.fine_tuning.alpha.graders.with_streaming_response.validate( grader={ "input": "input", "name": "name", "operation": "eq", "reference": "reference", "type": "string_check", }, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" grader = response.parse() assert_matches_type(GraderValidateResponse, grader, path=["response"]) assert cast(Any, response.is_closed) is True class TestAsyncGraders: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_run(self, async_client: AsyncOpenAI) -> None: grader = await async_client.fine_tuning.alpha.graders.run( grader={ "input": "input", "name": "name", "operation": "eq", "reference": "reference", "type": "string_check", }, model_sample="model_sample", ) assert_matches_type(GraderRunResponse, grader, path=["response"]) @parametrize async def test_method_run_with_all_params(self, async_client: AsyncOpenAI) -> None: grader = await async_client.fine_tuning.alpha.graders.run( grader={ "input": "input", "name": "name", "operation": "eq", "reference": "reference", "type": "string_check", }, model_sample="model_sample", item={}, ) assert_matches_type(GraderRunResponse, grader, path=["response"]) @parametrize async def test_raw_response_run(self, async_client: AsyncOpenAI) -> None: response = await async_client.fine_tuning.alpha.graders.with_raw_response.run( grader={ "input": "input", "name": "name", "operation": "eq", "reference": "reference", "type": "string_check", }, model_sample="model_sample", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" grader = response.parse() assert_matches_type(GraderRunResponse, grader, path=["response"]) @parametrize async def test_streaming_response_run(self, async_client: AsyncOpenAI) -> None: async with async_client.fine_tuning.alpha.graders.with_streaming_response.run( grader={ "input": "input", "name": "name", "operation": "eq", "reference": "reference", "type": "string_check", }, model_sample="model_sample", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" grader = await response.parse() assert_matches_type(GraderRunResponse, grader, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_validate(self, async_client: AsyncOpenAI) -> None: grader = await async_client.fine_tuning.alpha.graders.validate( grader={ "input": "input", "name": "name", "operation": "eq", "reference": "reference", "type": "string_check", }, ) assert_matches_type(GraderValidateResponse, grader, path=["response"]) @parametrize async def test_method_validate_with_all_params(self, async_client: AsyncOpenAI) -> None: grader = await async_client.fine_tuning.alpha.graders.validate( grader={ "input": "input", "name": "name", "operation": "eq", "reference": "reference", "type": "string_check", }, ) assert_matches_type(GraderValidateResponse, grader, path=["response"]) @parametrize async def test_raw_response_validate(self, async_client: AsyncOpenAI) -> None: response = await async_client.fine_tuning.alpha.graders.with_raw_response.validate( grader={ "input": "input", "name": "name", "operation": "eq", "reference": "reference", "type": "string_check", }, ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" grader = response.parse() assert_matches_type(GraderValidateResponse, grader, path=["response"]) @parametrize async def test_streaming_response_validate(self, async_client: AsyncOpenAI) -> None: async with async_client.fine_tuning.alpha.graders.with_streaming_response.validate( grader={ "input": "input", "name": "name", "operation": "eq", "reference": "reference", "type": "string_check", }, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" grader = await response.parse() assert_matches_type(GraderValidateResponse, grader, path=["response"]) assert cast(Any, response.is_closed) is True ================================================ FILE: tests/api_resources/fine_tuning/checkpoints/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/fine_tuning/checkpoints/test_permissions.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.pagination import SyncPage, AsyncPage, SyncConversationCursorPage, AsyncConversationCursorPage from openai.types.fine_tuning.checkpoints import ( PermissionListResponse, PermissionCreateResponse, PermissionDeleteResponse, PermissionRetrieveResponse, ) # pyright: reportDeprecated=false base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestPermissions: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: permission = client.fine_tuning.checkpoints.permissions.create( fine_tuned_model_checkpoint="ft:gpt-4o-mini-2024-07-18:org:weather:B7R9VjQd", project_ids=["string"], ) assert_matches_type(SyncPage[PermissionCreateResponse], permission, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.fine_tuning.checkpoints.permissions.with_raw_response.create( fine_tuned_model_checkpoint="ft:gpt-4o-mini-2024-07-18:org:weather:B7R9VjQd", project_ids=["string"], ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" permission = response.parse() assert_matches_type(SyncPage[PermissionCreateResponse], permission, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.fine_tuning.checkpoints.permissions.with_streaming_response.create( fine_tuned_model_checkpoint="ft:gpt-4o-mini-2024-07-18:org:weather:B7R9VjQd", project_ids=["string"], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" permission = response.parse() assert_matches_type(SyncPage[PermissionCreateResponse], permission, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_create(self, client: OpenAI) -> None: with pytest.raises( ValueError, match=r"Expected a non-empty value for `fine_tuned_model_checkpoint` but received ''" ): client.fine_tuning.checkpoints.permissions.with_raw_response.create( fine_tuned_model_checkpoint="", project_ids=["string"], ) @parametrize def test_method_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): permission = client.fine_tuning.checkpoints.permissions.retrieve( fine_tuned_model_checkpoint="ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert_matches_type(PermissionRetrieveResponse, permission, path=["response"]) @parametrize def test_method_retrieve_with_all_params(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): permission = client.fine_tuning.checkpoints.permissions.retrieve( fine_tuned_model_checkpoint="ft-AF1WoRqd3aJAHsqc9NY7iL8F", after="after", limit=0, order="ascending", project_id="project_id", ) assert_matches_type(PermissionRetrieveResponse, permission, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.fine_tuning.checkpoints.permissions.with_raw_response.retrieve( fine_tuned_model_checkpoint="ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" permission = response.parse() assert_matches_type(PermissionRetrieveResponse, permission, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.fine_tuning.checkpoints.permissions.with_streaming_response.retrieve( fine_tuned_model_checkpoint="ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" permission = response.parse() assert_matches_type(PermissionRetrieveResponse, permission, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises( ValueError, match=r"Expected a non-empty value for `fine_tuned_model_checkpoint` but received ''" ): client.fine_tuning.checkpoints.permissions.with_raw_response.retrieve( fine_tuned_model_checkpoint="", ) @parametrize def test_method_list(self, client: OpenAI) -> None: permission = client.fine_tuning.checkpoints.permissions.list( fine_tuned_model_checkpoint="ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert_matches_type(SyncConversationCursorPage[PermissionListResponse], permission, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: permission = client.fine_tuning.checkpoints.permissions.list( fine_tuned_model_checkpoint="ft-AF1WoRqd3aJAHsqc9NY7iL8F", after="after", limit=0, order="ascending", project_id="project_id", ) assert_matches_type(SyncConversationCursorPage[PermissionListResponse], permission, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.fine_tuning.checkpoints.permissions.with_raw_response.list( fine_tuned_model_checkpoint="ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" permission = response.parse() assert_matches_type(SyncConversationCursorPage[PermissionListResponse], permission, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.fine_tuning.checkpoints.permissions.with_streaming_response.list( fine_tuned_model_checkpoint="ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" permission = response.parse() assert_matches_type(SyncConversationCursorPage[PermissionListResponse], permission, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_list(self, client: OpenAI) -> None: with pytest.raises( ValueError, match=r"Expected a non-empty value for `fine_tuned_model_checkpoint` but received ''" ): client.fine_tuning.checkpoints.permissions.with_raw_response.list( fine_tuned_model_checkpoint="", ) @parametrize def test_method_delete(self, client: OpenAI) -> None: permission = client.fine_tuning.checkpoints.permissions.delete( permission_id="cp_zc4Q7MP6XxulcVzj4MZdwsAB", fine_tuned_model_checkpoint="ft:gpt-4o-mini-2024-07-18:org:weather:B7R9VjQd", ) assert_matches_type(PermissionDeleteResponse, permission, path=["response"]) @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: response = client.fine_tuning.checkpoints.permissions.with_raw_response.delete( permission_id="cp_zc4Q7MP6XxulcVzj4MZdwsAB", fine_tuned_model_checkpoint="ft:gpt-4o-mini-2024-07-18:org:weather:B7R9VjQd", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" permission = response.parse() assert_matches_type(PermissionDeleteResponse, permission, path=["response"]) @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with client.fine_tuning.checkpoints.permissions.with_streaming_response.delete( permission_id="cp_zc4Q7MP6XxulcVzj4MZdwsAB", fine_tuned_model_checkpoint="ft:gpt-4o-mini-2024-07-18:org:weather:B7R9VjQd", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" permission = response.parse() assert_matches_type(PermissionDeleteResponse, permission, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.raises( ValueError, match=r"Expected a non-empty value for `fine_tuned_model_checkpoint` but received ''" ): client.fine_tuning.checkpoints.permissions.with_raw_response.delete( permission_id="cp_zc4Q7MP6XxulcVzj4MZdwsAB", fine_tuned_model_checkpoint="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `permission_id` but received ''"): client.fine_tuning.checkpoints.permissions.with_raw_response.delete( permission_id="", fine_tuned_model_checkpoint="ft:gpt-4o-mini-2024-07-18:org:weather:B7R9VjQd", ) class TestAsyncPermissions: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: permission = await async_client.fine_tuning.checkpoints.permissions.create( fine_tuned_model_checkpoint="ft:gpt-4o-mini-2024-07-18:org:weather:B7R9VjQd", project_ids=["string"], ) assert_matches_type(AsyncPage[PermissionCreateResponse], permission, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.fine_tuning.checkpoints.permissions.with_raw_response.create( fine_tuned_model_checkpoint="ft:gpt-4o-mini-2024-07-18:org:weather:B7R9VjQd", project_ids=["string"], ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" permission = response.parse() assert_matches_type(AsyncPage[PermissionCreateResponse], permission, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.fine_tuning.checkpoints.permissions.with_streaming_response.create( fine_tuned_model_checkpoint="ft:gpt-4o-mini-2024-07-18:org:weather:B7R9VjQd", project_ids=["string"], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" permission = await response.parse() assert_matches_type(AsyncPage[PermissionCreateResponse], permission, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_create(self, async_client: AsyncOpenAI) -> None: with pytest.raises( ValueError, match=r"Expected a non-empty value for `fine_tuned_model_checkpoint` but received ''" ): await async_client.fine_tuning.checkpoints.permissions.with_raw_response.create( fine_tuned_model_checkpoint="", project_ids=["string"], ) @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): permission = await async_client.fine_tuning.checkpoints.permissions.retrieve( fine_tuned_model_checkpoint="ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert_matches_type(PermissionRetrieveResponse, permission, path=["response"]) @parametrize async def test_method_retrieve_with_all_params(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): permission = await async_client.fine_tuning.checkpoints.permissions.retrieve( fine_tuned_model_checkpoint="ft-AF1WoRqd3aJAHsqc9NY7iL8F", after="after", limit=0, order="ascending", project_id="project_id", ) assert_matches_type(PermissionRetrieveResponse, permission, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.fine_tuning.checkpoints.permissions.with_raw_response.retrieve( fine_tuned_model_checkpoint="ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" permission = response.parse() assert_matches_type(PermissionRetrieveResponse, permission, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.fine_tuning.checkpoints.permissions.with_streaming_response.retrieve( fine_tuned_model_checkpoint="ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" permission = await response.parse() assert_matches_type(PermissionRetrieveResponse, permission, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises( ValueError, match=r"Expected a non-empty value for `fine_tuned_model_checkpoint` but received ''" ): await async_client.fine_tuning.checkpoints.permissions.with_raw_response.retrieve( fine_tuned_model_checkpoint="", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: permission = await async_client.fine_tuning.checkpoints.permissions.list( fine_tuned_model_checkpoint="ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert_matches_type(AsyncConversationCursorPage[PermissionListResponse], permission, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: permission = await async_client.fine_tuning.checkpoints.permissions.list( fine_tuned_model_checkpoint="ft-AF1WoRqd3aJAHsqc9NY7iL8F", after="after", limit=0, order="ascending", project_id="project_id", ) assert_matches_type(AsyncConversationCursorPage[PermissionListResponse], permission, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.fine_tuning.checkpoints.permissions.with_raw_response.list( fine_tuned_model_checkpoint="ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" permission = response.parse() assert_matches_type(AsyncConversationCursorPage[PermissionListResponse], permission, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.fine_tuning.checkpoints.permissions.with_streaming_response.list( fine_tuned_model_checkpoint="ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" permission = await response.parse() assert_matches_type(AsyncConversationCursorPage[PermissionListResponse], permission, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_list(self, async_client: AsyncOpenAI) -> None: with pytest.raises( ValueError, match=r"Expected a non-empty value for `fine_tuned_model_checkpoint` but received ''" ): await async_client.fine_tuning.checkpoints.permissions.with_raw_response.list( fine_tuned_model_checkpoint="", ) @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: permission = await async_client.fine_tuning.checkpoints.permissions.delete( permission_id="cp_zc4Q7MP6XxulcVzj4MZdwsAB", fine_tuned_model_checkpoint="ft:gpt-4o-mini-2024-07-18:org:weather:B7R9VjQd", ) assert_matches_type(PermissionDeleteResponse, permission, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: response = await async_client.fine_tuning.checkpoints.permissions.with_raw_response.delete( permission_id="cp_zc4Q7MP6XxulcVzj4MZdwsAB", fine_tuned_model_checkpoint="ft:gpt-4o-mini-2024-07-18:org:weather:B7R9VjQd", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" permission = response.parse() assert_matches_type(PermissionDeleteResponse, permission, path=["response"]) @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: async with async_client.fine_tuning.checkpoints.permissions.with_streaming_response.delete( permission_id="cp_zc4Q7MP6XxulcVzj4MZdwsAB", fine_tuned_model_checkpoint="ft:gpt-4o-mini-2024-07-18:org:weather:B7R9VjQd", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" permission = await response.parse() assert_matches_type(PermissionDeleteResponse, permission, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.raises( ValueError, match=r"Expected a non-empty value for `fine_tuned_model_checkpoint` but received ''" ): await async_client.fine_tuning.checkpoints.permissions.with_raw_response.delete( permission_id="cp_zc4Q7MP6XxulcVzj4MZdwsAB", fine_tuned_model_checkpoint="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `permission_id` but received ''"): await async_client.fine_tuning.checkpoints.permissions.with_raw_response.delete( permission_id="", fine_tuned_model_checkpoint="ft:gpt-4o-mini-2024-07-18:org:weather:B7R9VjQd", ) ================================================ FILE: tests/api_resources/fine_tuning/jobs/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/fine_tuning/jobs/test_checkpoints.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.pagination import SyncCursorPage, AsyncCursorPage from openai.types.fine_tuning.jobs import FineTuningJobCheckpoint base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestCheckpoints: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_list(self, client: OpenAI) -> None: checkpoint = client.fine_tuning.jobs.checkpoints.list( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert_matches_type(SyncCursorPage[FineTuningJobCheckpoint], checkpoint, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: checkpoint = client.fine_tuning.jobs.checkpoints.list( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", after="string", limit=0, ) assert_matches_type(SyncCursorPage[FineTuningJobCheckpoint], checkpoint, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.fine_tuning.jobs.checkpoints.with_raw_response.list( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" checkpoint = response.parse() assert_matches_type(SyncCursorPage[FineTuningJobCheckpoint], checkpoint, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.fine_tuning.jobs.checkpoints.with_streaming_response.list( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" checkpoint = response.parse() assert_matches_type(SyncCursorPage[FineTuningJobCheckpoint], checkpoint, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_list(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `fine_tuning_job_id` but received ''"): client.fine_tuning.jobs.checkpoints.with_raw_response.list( "", ) class TestAsyncCheckpoints: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: checkpoint = await async_client.fine_tuning.jobs.checkpoints.list( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert_matches_type(AsyncCursorPage[FineTuningJobCheckpoint], checkpoint, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: checkpoint = await async_client.fine_tuning.jobs.checkpoints.list( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", after="string", limit=0, ) assert_matches_type(AsyncCursorPage[FineTuningJobCheckpoint], checkpoint, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.fine_tuning.jobs.checkpoints.with_raw_response.list( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" checkpoint = response.parse() assert_matches_type(AsyncCursorPage[FineTuningJobCheckpoint], checkpoint, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.fine_tuning.jobs.checkpoints.with_streaming_response.list( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" checkpoint = await response.parse() assert_matches_type(AsyncCursorPage[FineTuningJobCheckpoint], checkpoint, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_list(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `fine_tuning_job_id` but received ''"): await async_client.fine_tuning.jobs.checkpoints.with_raw_response.list( "", ) ================================================ FILE: tests/api_resources/fine_tuning/test_jobs.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.pagination import SyncCursorPage, AsyncCursorPage from openai.types.fine_tuning import ( FineTuningJob, FineTuningJobEvent, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestJobs: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: job = client.fine_tuning.jobs.create( model="gpt-4o-mini", training_file="file-abc123", ) assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: job = client.fine_tuning.jobs.create( model="gpt-4o-mini", training_file="file-abc123", hyperparameters={ "batch_size": "auto", "learning_rate_multiplier": "auto", "n_epochs": "auto", }, integrations=[ { "type": "wandb", "wandb": { "project": "my-wandb-project", "entity": "entity", "name": "name", "tags": ["custom-tag"], }, } ], metadata={"foo": "string"}, method={ "type": "supervised", "dpo": { "hyperparameters": { "batch_size": "auto", "beta": "auto", "learning_rate_multiplier": "auto", "n_epochs": "auto", } }, "reinforcement": { "grader": { "input": "input", "name": "name", "operation": "eq", "reference": "reference", "type": "string_check", }, "hyperparameters": { "batch_size": "auto", "compute_multiplier": "auto", "eval_interval": "auto", "eval_samples": "auto", "learning_rate_multiplier": "auto", "n_epochs": "auto", "reasoning_effort": "default", }, }, "supervised": { "hyperparameters": { "batch_size": "auto", "learning_rate_multiplier": "auto", "n_epochs": "auto", } }, }, seed=42, suffix="x", validation_file="file-abc123", ) assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.fine_tuning.jobs.with_raw_response.create( model="gpt-4o-mini", training_file="file-abc123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.fine_tuning.jobs.with_streaming_response.create( model="gpt-4o-mini", training_file="file-abc123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_retrieve(self, client: OpenAI) -> None: job = client.fine_tuning.jobs.retrieve( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: response = client.fine_tuning.jobs.with_raw_response.retrieve( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with client.fine_tuning.jobs.with_streaming_response.retrieve( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `fine_tuning_job_id` but received ''"): client.fine_tuning.jobs.with_raw_response.retrieve( "", ) @parametrize def test_method_list(self, client: OpenAI) -> None: job = client.fine_tuning.jobs.list() assert_matches_type(SyncCursorPage[FineTuningJob], job, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: job = client.fine_tuning.jobs.list( after="string", limit=0, metadata={"foo": "string"}, ) assert_matches_type(SyncCursorPage[FineTuningJob], job, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.fine_tuning.jobs.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(SyncCursorPage[FineTuningJob], job, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.fine_tuning.jobs.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(SyncCursorPage[FineTuningJob], job, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_cancel(self, client: OpenAI) -> None: job = client.fine_tuning.jobs.cancel( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize def test_raw_response_cancel(self, client: OpenAI) -> None: response = client.fine_tuning.jobs.with_raw_response.cancel( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize def test_streaming_response_cancel(self, client: OpenAI) -> None: with client.fine_tuning.jobs.with_streaming_response.cancel( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_cancel(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `fine_tuning_job_id` but received ''"): client.fine_tuning.jobs.with_raw_response.cancel( "", ) @parametrize def test_method_list_events(self, client: OpenAI) -> None: job = client.fine_tuning.jobs.list_events( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert_matches_type(SyncCursorPage[FineTuningJobEvent], job, path=["response"]) @parametrize def test_method_list_events_with_all_params(self, client: OpenAI) -> None: job = client.fine_tuning.jobs.list_events( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", after="string", limit=0, ) assert_matches_type(SyncCursorPage[FineTuningJobEvent], job, path=["response"]) @parametrize def test_raw_response_list_events(self, client: OpenAI) -> None: response = client.fine_tuning.jobs.with_raw_response.list_events( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(SyncCursorPage[FineTuningJobEvent], job, path=["response"]) @parametrize def test_streaming_response_list_events(self, client: OpenAI) -> None: with client.fine_tuning.jobs.with_streaming_response.list_events( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(SyncCursorPage[FineTuningJobEvent], job, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_list_events(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `fine_tuning_job_id` but received ''"): client.fine_tuning.jobs.with_raw_response.list_events( "", ) @parametrize def test_method_pause(self, client: OpenAI) -> None: job = client.fine_tuning.jobs.pause( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize def test_raw_response_pause(self, client: OpenAI) -> None: response = client.fine_tuning.jobs.with_raw_response.pause( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize def test_streaming_response_pause(self, client: OpenAI) -> None: with client.fine_tuning.jobs.with_streaming_response.pause( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_pause(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `fine_tuning_job_id` but received ''"): client.fine_tuning.jobs.with_raw_response.pause( "", ) @parametrize def test_method_resume(self, client: OpenAI) -> None: job = client.fine_tuning.jobs.resume( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize def test_raw_response_resume(self, client: OpenAI) -> None: response = client.fine_tuning.jobs.with_raw_response.resume( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize def test_streaming_response_resume(self, client: OpenAI) -> None: with client.fine_tuning.jobs.with_streaming_response.resume( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_resume(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `fine_tuning_job_id` but received ''"): client.fine_tuning.jobs.with_raw_response.resume( "", ) class TestAsyncJobs: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: job = await async_client.fine_tuning.jobs.create( model="gpt-4o-mini", training_file="file-abc123", ) assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: job = await async_client.fine_tuning.jobs.create( model="gpt-4o-mini", training_file="file-abc123", hyperparameters={ "batch_size": "auto", "learning_rate_multiplier": "auto", "n_epochs": "auto", }, integrations=[ { "type": "wandb", "wandb": { "project": "my-wandb-project", "entity": "entity", "name": "name", "tags": ["custom-tag"], }, } ], metadata={"foo": "string"}, method={ "type": "supervised", "dpo": { "hyperparameters": { "batch_size": "auto", "beta": "auto", "learning_rate_multiplier": "auto", "n_epochs": "auto", } }, "reinforcement": { "grader": { "input": "input", "name": "name", "operation": "eq", "reference": "reference", "type": "string_check", }, "hyperparameters": { "batch_size": "auto", "compute_multiplier": "auto", "eval_interval": "auto", "eval_samples": "auto", "learning_rate_multiplier": "auto", "n_epochs": "auto", "reasoning_effort": "default", }, }, "supervised": { "hyperparameters": { "batch_size": "auto", "learning_rate_multiplier": "auto", "n_epochs": "auto", } }, }, seed=42, suffix="x", validation_file="file-abc123", ) assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.fine_tuning.jobs.with_raw_response.create( model="gpt-4o-mini", training_file="file-abc123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.fine_tuning.jobs.with_streaming_response.create( model="gpt-4o-mini", training_file="file-abc123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = await response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: job = await async_client.fine_tuning.jobs.retrieve( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: response = await async_client.fine_tuning.jobs.with_raw_response.retrieve( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: async with async_client.fine_tuning.jobs.with_streaming_response.retrieve( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = await response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `fine_tuning_job_id` but received ''"): await async_client.fine_tuning.jobs.with_raw_response.retrieve( "", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: job = await async_client.fine_tuning.jobs.list() assert_matches_type(AsyncCursorPage[FineTuningJob], job, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: job = await async_client.fine_tuning.jobs.list( after="string", limit=0, metadata={"foo": "string"}, ) assert_matches_type(AsyncCursorPage[FineTuningJob], job, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.fine_tuning.jobs.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(AsyncCursorPage[FineTuningJob], job, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.fine_tuning.jobs.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = await response.parse() assert_matches_type(AsyncCursorPage[FineTuningJob], job, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_cancel(self, async_client: AsyncOpenAI) -> None: job = await async_client.fine_tuning.jobs.cancel( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize async def test_raw_response_cancel(self, async_client: AsyncOpenAI) -> None: response = await async_client.fine_tuning.jobs.with_raw_response.cancel( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize async def test_streaming_response_cancel(self, async_client: AsyncOpenAI) -> None: async with async_client.fine_tuning.jobs.with_streaming_response.cancel( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = await response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_cancel(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `fine_tuning_job_id` but received ''"): await async_client.fine_tuning.jobs.with_raw_response.cancel( "", ) @parametrize async def test_method_list_events(self, async_client: AsyncOpenAI) -> None: job = await async_client.fine_tuning.jobs.list_events( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert_matches_type(AsyncCursorPage[FineTuningJobEvent], job, path=["response"]) @parametrize async def test_method_list_events_with_all_params(self, async_client: AsyncOpenAI) -> None: job = await async_client.fine_tuning.jobs.list_events( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", after="string", limit=0, ) assert_matches_type(AsyncCursorPage[FineTuningJobEvent], job, path=["response"]) @parametrize async def test_raw_response_list_events(self, async_client: AsyncOpenAI) -> None: response = await async_client.fine_tuning.jobs.with_raw_response.list_events( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(AsyncCursorPage[FineTuningJobEvent], job, path=["response"]) @parametrize async def test_streaming_response_list_events(self, async_client: AsyncOpenAI) -> None: async with async_client.fine_tuning.jobs.with_streaming_response.list_events( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = await response.parse() assert_matches_type(AsyncCursorPage[FineTuningJobEvent], job, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_list_events(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `fine_tuning_job_id` but received ''"): await async_client.fine_tuning.jobs.with_raw_response.list_events( "", ) @parametrize async def test_method_pause(self, async_client: AsyncOpenAI) -> None: job = await async_client.fine_tuning.jobs.pause( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize async def test_raw_response_pause(self, async_client: AsyncOpenAI) -> None: response = await async_client.fine_tuning.jobs.with_raw_response.pause( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize async def test_streaming_response_pause(self, async_client: AsyncOpenAI) -> None: async with async_client.fine_tuning.jobs.with_streaming_response.pause( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = await response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_pause(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `fine_tuning_job_id` but received ''"): await async_client.fine_tuning.jobs.with_raw_response.pause( "", ) @parametrize async def test_method_resume(self, async_client: AsyncOpenAI) -> None: job = await async_client.fine_tuning.jobs.resume( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize async def test_raw_response_resume(self, async_client: AsyncOpenAI) -> None: response = await async_client.fine_tuning.jobs.with_raw_response.resume( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) @parametrize async def test_streaming_response_resume(self, async_client: AsyncOpenAI) -> None: async with async_client.fine_tuning.jobs.with_streaming_response.resume( "ft-AF1WoRqd3aJAHsqc9NY7iL8F", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" job = await response.parse() assert_matches_type(FineTuningJob, job, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_resume(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `fine_tuning_job_id` but received ''"): await async_client.fine_tuning.jobs.with_raw_response.resume( "", ) ================================================ FILE: tests/api_resources/realtime/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/realtime/test_calls.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import httpx import pytest from respx import MockRouter import openai._legacy_response as _legacy_response from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type # pyright: reportDeprecated=false base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestCalls: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize @pytest.mark.respx(base_url=base_url) def test_method_create(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.post("/realtime/calls").mock(return_value=httpx.Response(200, json={"foo": "bar"})) call = client.realtime.calls.create( sdp="sdp", ) assert isinstance(call, _legacy_response.HttpxBinaryResponseContent) assert call.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) def test_method_create_with_all_params(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.post("/realtime/calls").mock(return_value=httpx.Response(200, json={"foo": "bar"})) call = client.realtime.calls.create( sdp="sdp", session={ "type": "realtime", "audio": { "input": { "format": { "rate": 24000, "type": "audio/pcm", }, "noise_reduction": {"type": "near_field"}, "transcription": { "language": "language", "model": "string", "prompt": "prompt", }, "turn_detection": { "type": "server_vad", "create_response": True, "idle_timeout_ms": 5000, "interrupt_response": True, "prefix_padding_ms": 0, "silence_duration_ms": 0, "threshold": 0, }, }, "output": { "format": { "rate": 24000, "type": "audio/pcm", }, "speed": 0.25, "voice": "string", }, }, "include": ["item.input_audio_transcription.logprobs"], "instructions": "instructions", "max_output_tokens": 0, "model": "string", "output_modalities": ["text"], "prompt": { "id": "id", "variables": {"foo": "string"}, "version": "version", }, "tool_choice": "none", "tools": [ { "description": "description", "name": "name", "parameters": {}, "type": "function", } ], "tracing": "auto", "truncation": "auto", }, ) assert isinstance(call, _legacy_response.HttpxBinaryResponseContent) assert call.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) def test_raw_response_create(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.post("/realtime/calls").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = client.realtime.calls.with_raw_response.create( sdp="sdp", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = response.parse() assert_matches_type(_legacy_response.HttpxBinaryResponseContent, call, path=["response"]) @parametrize @pytest.mark.respx(base_url=base_url) def test_streaming_response_create(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.post("/realtime/calls").mock(return_value=httpx.Response(200, json={"foo": "bar"})) with client.realtime.calls.with_streaming_response.create( sdp="sdp", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = response.parse() assert_matches_type(bytes, call, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_accept(self, client: OpenAI) -> None: call = client.realtime.calls.accept( call_id="call_id", type="realtime", ) assert call is None @parametrize def test_method_accept_with_all_params(self, client: OpenAI) -> None: call = client.realtime.calls.accept( call_id="call_id", type="realtime", audio={ "input": { "format": { "rate": 24000, "type": "audio/pcm", }, "noise_reduction": {"type": "near_field"}, "transcription": { "language": "language", "model": "string", "prompt": "prompt", }, "turn_detection": { "type": "server_vad", "create_response": True, "idle_timeout_ms": 5000, "interrupt_response": True, "prefix_padding_ms": 0, "silence_duration_ms": 0, "threshold": 0, }, }, "output": { "format": { "rate": 24000, "type": "audio/pcm", }, "speed": 0.25, "voice": "string", }, }, include=["item.input_audio_transcription.logprobs"], instructions="instructions", max_output_tokens=0, model="string", output_modalities=["text"], prompt={ "id": "id", "variables": {"foo": "string"}, "version": "version", }, tool_choice="none", tools=[ { "description": "description", "name": "name", "parameters": {}, "type": "function", } ], tracing="auto", truncation="auto", ) assert call is None @parametrize def test_raw_response_accept(self, client: OpenAI) -> None: response = client.realtime.calls.with_raw_response.accept( call_id="call_id", type="realtime", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = response.parse() assert call is None @parametrize def test_streaming_response_accept(self, client: OpenAI) -> None: with client.realtime.calls.with_streaming_response.accept( call_id="call_id", type="realtime", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = response.parse() assert call is None assert cast(Any, response.is_closed) is True @parametrize def test_path_params_accept(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `call_id` but received ''"): client.realtime.calls.with_raw_response.accept( call_id="", type="realtime", ) @parametrize def test_method_hangup(self, client: OpenAI) -> None: call = client.realtime.calls.hangup( "call_id", ) assert call is None @parametrize def test_raw_response_hangup(self, client: OpenAI) -> None: response = client.realtime.calls.with_raw_response.hangup( "call_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = response.parse() assert call is None @parametrize def test_streaming_response_hangup(self, client: OpenAI) -> None: with client.realtime.calls.with_streaming_response.hangup( "call_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = response.parse() assert call is None assert cast(Any, response.is_closed) is True @parametrize def test_path_params_hangup(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `call_id` but received ''"): client.realtime.calls.with_raw_response.hangup( "", ) @parametrize def test_method_refer(self, client: OpenAI) -> None: call = client.realtime.calls.refer( call_id="call_id", target_uri="tel:+14155550123", ) assert call is None @parametrize def test_raw_response_refer(self, client: OpenAI) -> None: response = client.realtime.calls.with_raw_response.refer( call_id="call_id", target_uri="tel:+14155550123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = response.parse() assert call is None @parametrize def test_streaming_response_refer(self, client: OpenAI) -> None: with client.realtime.calls.with_streaming_response.refer( call_id="call_id", target_uri="tel:+14155550123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = response.parse() assert call is None assert cast(Any, response.is_closed) is True @parametrize def test_path_params_refer(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `call_id` but received ''"): client.realtime.calls.with_raw_response.refer( call_id="", target_uri="tel:+14155550123", ) @parametrize def test_method_reject(self, client: OpenAI) -> None: call = client.realtime.calls.reject( call_id="call_id", ) assert call is None @parametrize def test_method_reject_with_all_params(self, client: OpenAI) -> None: call = client.realtime.calls.reject( call_id="call_id", status_code=486, ) assert call is None @parametrize def test_raw_response_reject(self, client: OpenAI) -> None: response = client.realtime.calls.with_raw_response.reject( call_id="call_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = response.parse() assert call is None @parametrize def test_streaming_response_reject(self, client: OpenAI) -> None: with client.realtime.calls.with_streaming_response.reject( call_id="call_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = response.parse() assert call is None assert cast(Any, response.is_closed) is True @parametrize def test_path_params_reject(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `call_id` but received ''"): client.realtime.calls.with_raw_response.reject( call_id="", ) class TestAsyncCalls: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize @pytest.mark.respx(base_url=base_url) async def test_method_create(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.post("/realtime/calls").mock(return_value=httpx.Response(200, json={"foo": "bar"})) call = await async_client.realtime.calls.create( sdp="sdp", ) assert isinstance(call, _legacy_response.HttpxBinaryResponseContent) assert call.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) async def test_method_create_with_all_params(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.post("/realtime/calls").mock(return_value=httpx.Response(200, json={"foo": "bar"})) call = await async_client.realtime.calls.create( sdp="sdp", session={ "type": "realtime", "audio": { "input": { "format": { "rate": 24000, "type": "audio/pcm", }, "noise_reduction": {"type": "near_field"}, "transcription": { "language": "language", "model": "string", "prompt": "prompt", }, "turn_detection": { "type": "server_vad", "create_response": True, "idle_timeout_ms": 5000, "interrupt_response": True, "prefix_padding_ms": 0, "silence_duration_ms": 0, "threshold": 0, }, }, "output": { "format": { "rate": 24000, "type": "audio/pcm", }, "speed": 0.25, "voice": "string", }, }, "include": ["item.input_audio_transcription.logprobs"], "instructions": "instructions", "max_output_tokens": 0, "model": "string", "output_modalities": ["text"], "prompt": { "id": "id", "variables": {"foo": "string"}, "version": "version", }, "tool_choice": "none", "tools": [ { "description": "description", "name": "name", "parameters": {}, "type": "function", } ], "tracing": "auto", "truncation": "auto", }, ) assert isinstance(call, _legacy_response.HttpxBinaryResponseContent) assert call.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) async def test_raw_response_create(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.post("/realtime/calls").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = await async_client.realtime.calls.with_raw_response.create( sdp="sdp", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = response.parse() assert_matches_type(_legacy_response.HttpxBinaryResponseContent, call, path=["response"]) @parametrize @pytest.mark.respx(base_url=base_url) async def test_streaming_response_create(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.post("/realtime/calls").mock(return_value=httpx.Response(200, json={"foo": "bar"})) async with async_client.realtime.calls.with_streaming_response.create( sdp="sdp", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = await response.parse() assert_matches_type(bytes, call, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_accept(self, async_client: AsyncOpenAI) -> None: call = await async_client.realtime.calls.accept( call_id="call_id", type="realtime", ) assert call is None @parametrize async def test_method_accept_with_all_params(self, async_client: AsyncOpenAI) -> None: call = await async_client.realtime.calls.accept( call_id="call_id", type="realtime", audio={ "input": { "format": { "rate": 24000, "type": "audio/pcm", }, "noise_reduction": {"type": "near_field"}, "transcription": { "language": "language", "model": "string", "prompt": "prompt", }, "turn_detection": { "type": "server_vad", "create_response": True, "idle_timeout_ms": 5000, "interrupt_response": True, "prefix_padding_ms": 0, "silence_duration_ms": 0, "threshold": 0, }, }, "output": { "format": { "rate": 24000, "type": "audio/pcm", }, "speed": 0.25, "voice": "string", }, }, include=["item.input_audio_transcription.logprobs"], instructions="instructions", max_output_tokens=0, model="string", output_modalities=["text"], prompt={ "id": "id", "variables": {"foo": "string"}, "version": "version", }, tool_choice="none", tools=[ { "description": "description", "name": "name", "parameters": {}, "type": "function", } ], tracing="auto", truncation="auto", ) assert call is None @parametrize async def test_raw_response_accept(self, async_client: AsyncOpenAI) -> None: response = await async_client.realtime.calls.with_raw_response.accept( call_id="call_id", type="realtime", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = response.parse() assert call is None @parametrize async def test_streaming_response_accept(self, async_client: AsyncOpenAI) -> None: async with async_client.realtime.calls.with_streaming_response.accept( call_id="call_id", type="realtime", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = await response.parse() assert call is None assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_accept(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `call_id` but received ''"): await async_client.realtime.calls.with_raw_response.accept( call_id="", type="realtime", ) @parametrize async def test_method_hangup(self, async_client: AsyncOpenAI) -> None: call = await async_client.realtime.calls.hangup( "call_id", ) assert call is None @parametrize async def test_raw_response_hangup(self, async_client: AsyncOpenAI) -> None: response = await async_client.realtime.calls.with_raw_response.hangup( "call_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = response.parse() assert call is None @parametrize async def test_streaming_response_hangup(self, async_client: AsyncOpenAI) -> None: async with async_client.realtime.calls.with_streaming_response.hangup( "call_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = await response.parse() assert call is None assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_hangup(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `call_id` but received ''"): await async_client.realtime.calls.with_raw_response.hangup( "", ) @parametrize async def test_method_refer(self, async_client: AsyncOpenAI) -> None: call = await async_client.realtime.calls.refer( call_id="call_id", target_uri="tel:+14155550123", ) assert call is None @parametrize async def test_raw_response_refer(self, async_client: AsyncOpenAI) -> None: response = await async_client.realtime.calls.with_raw_response.refer( call_id="call_id", target_uri="tel:+14155550123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = response.parse() assert call is None @parametrize async def test_streaming_response_refer(self, async_client: AsyncOpenAI) -> None: async with async_client.realtime.calls.with_streaming_response.refer( call_id="call_id", target_uri="tel:+14155550123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = await response.parse() assert call is None assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_refer(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `call_id` but received ''"): await async_client.realtime.calls.with_raw_response.refer( call_id="", target_uri="tel:+14155550123", ) @parametrize async def test_method_reject(self, async_client: AsyncOpenAI) -> None: call = await async_client.realtime.calls.reject( call_id="call_id", ) assert call is None @parametrize async def test_method_reject_with_all_params(self, async_client: AsyncOpenAI) -> None: call = await async_client.realtime.calls.reject( call_id="call_id", status_code=486, ) assert call is None @parametrize async def test_raw_response_reject(self, async_client: AsyncOpenAI) -> None: response = await async_client.realtime.calls.with_raw_response.reject( call_id="call_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = response.parse() assert call is None @parametrize async def test_streaming_response_reject(self, async_client: AsyncOpenAI) -> None: async with async_client.realtime.calls.with_streaming_response.reject( call_id="call_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" call = await response.parse() assert call is None assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_reject(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `call_id` but received ''"): await async_client.realtime.calls.with_raw_response.reject( call_id="", ) ================================================ FILE: tests/api_resources/realtime/test_client_secrets.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types.realtime import ClientSecretCreateResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestClientSecrets: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: client_secret = client.realtime.client_secrets.create() assert_matches_type(ClientSecretCreateResponse, client_secret, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: client_secret = client.realtime.client_secrets.create( expires_after={ "anchor": "created_at", "seconds": 10, }, session={ "type": "realtime", "audio": { "input": { "format": { "rate": 24000, "type": "audio/pcm", }, "noise_reduction": {"type": "near_field"}, "transcription": { "language": "language", "model": "string", "prompt": "prompt", }, "turn_detection": { "type": "server_vad", "create_response": True, "idle_timeout_ms": 5000, "interrupt_response": True, "prefix_padding_ms": 0, "silence_duration_ms": 0, "threshold": 0, }, }, "output": { "format": { "rate": 24000, "type": "audio/pcm", }, "speed": 0.25, "voice": "string", }, }, "include": ["item.input_audio_transcription.logprobs"], "instructions": "instructions", "max_output_tokens": 0, "model": "string", "output_modalities": ["text"], "prompt": { "id": "id", "variables": {"foo": "string"}, "version": "version", }, "tool_choice": "none", "tools": [ { "description": "description", "name": "name", "parameters": {}, "type": "function", } ], "tracing": "auto", "truncation": "auto", }, ) assert_matches_type(ClientSecretCreateResponse, client_secret, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.realtime.client_secrets.with_raw_response.create() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" client_secret = response.parse() assert_matches_type(ClientSecretCreateResponse, client_secret, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.realtime.client_secrets.with_streaming_response.create() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" client_secret = response.parse() assert_matches_type(ClientSecretCreateResponse, client_secret, path=["response"]) assert cast(Any, response.is_closed) is True class TestAsyncClientSecrets: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: client_secret = await async_client.realtime.client_secrets.create() assert_matches_type(ClientSecretCreateResponse, client_secret, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: client_secret = await async_client.realtime.client_secrets.create( expires_after={ "anchor": "created_at", "seconds": 10, }, session={ "type": "realtime", "audio": { "input": { "format": { "rate": 24000, "type": "audio/pcm", }, "noise_reduction": {"type": "near_field"}, "transcription": { "language": "language", "model": "string", "prompt": "prompt", }, "turn_detection": { "type": "server_vad", "create_response": True, "idle_timeout_ms": 5000, "interrupt_response": True, "prefix_padding_ms": 0, "silence_duration_ms": 0, "threshold": 0, }, }, "output": { "format": { "rate": 24000, "type": "audio/pcm", }, "speed": 0.25, "voice": "string", }, }, "include": ["item.input_audio_transcription.logprobs"], "instructions": "instructions", "max_output_tokens": 0, "model": "string", "output_modalities": ["text"], "prompt": { "id": "id", "variables": {"foo": "string"}, "version": "version", }, "tool_choice": "none", "tools": [ { "description": "description", "name": "name", "parameters": {}, "type": "function", } ], "tracing": "auto", "truncation": "auto", }, ) assert_matches_type(ClientSecretCreateResponse, client_secret, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.realtime.client_secrets.with_raw_response.create() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" client_secret = response.parse() assert_matches_type(ClientSecretCreateResponse, client_secret, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.realtime.client_secrets.with_streaming_response.create() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" client_secret = await response.parse() assert_matches_type(ClientSecretCreateResponse, client_secret, path=["response"]) assert cast(Any, response.is_closed) is True ================================================ FILE: tests/api_resources/responses/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/responses/test_input_items.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.pagination import SyncCursorPage, AsyncCursorPage from openai.types.responses import ResponseItem base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestInputItems: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_list(self, client: OpenAI) -> None: input_item = client.responses.input_items.list( response_id="response_id", ) assert_matches_type(SyncCursorPage[ResponseItem], input_item, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: input_item = client.responses.input_items.list( response_id="response_id", after="after", include=["file_search_call.results"], limit=0, order="asc", ) assert_matches_type(SyncCursorPage[ResponseItem], input_item, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.responses.input_items.with_raw_response.list( response_id="response_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" input_item = response.parse() assert_matches_type(SyncCursorPage[ResponseItem], input_item, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.responses.input_items.with_streaming_response.list( response_id="response_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" input_item = response.parse() assert_matches_type(SyncCursorPage[ResponseItem], input_item, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_list(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `response_id` but received ''"): client.responses.input_items.with_raw_response.list( response_id="", ) class TestAsyncInputItems: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: input_item = await async_client.responses.input_items.list( response_id="response_id", ) assert_matches_type(AsyncCursorPage[ResponseItem], input_item, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: input_item = await async_client.responses.input_items.list( response_id="response_id", after="after", include=["file_search_call.results"], limit=0, order="asc", ) assert_matches_type(AsyncCursorPage[ResponseItem], input_item, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.responses.input_items.with_raw_response.list( response_id="response_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" input_item = response.parse() assert_matches_type(AsyncCursorPage[ResponseItem], input_item, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.responses.input_items.with_streaming_response.list( response_id="response_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" input_item = await response.parse() assert_matches_type(AsyncCursorPage[ResponseItem], input_item, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_list(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `response_id` but received ''"): await async_client.responses.input_items.with_raw_response.list( response_id="", ) ================================================ FILE: tests/api_resources/responses/test_input_tokens.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types.responses import InputTokenCountResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestInputTokens: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_count(self, client: OpenAI) -> None: input_token = client.responses.input_tokens.count() assert_matches_type(InputTokenCountResponse, input_token, path=["response"]) @parametrize def test_method_count_with_all_params(self, client: OpenAI) -> None: input_token = client.responses.input_tokens.count( conversation="string", input="string", instructions="instructions", model="model", parallel_tool_calls=True, previous_response_id="resp_123", reasoning={ "effort": "none", "generate_summary": "auto", "summary": "auto", }, text={ "format": {"type": "text"}, "verbosity": "low", }, tool_choice="none", tools=[ { "name": "name", "parameters": {"foo": "bar"}, "strict": True, "type": "function", "defer_loading": True, "description": "description", } ], truncation="auto", ) assert_matches_type(InputTokenCountResponse, input_token, path=["response"]) @parametrize def test_raw_response_count(self, client: OpenAI) -> None: response = client.responses.input_tokens.with_raw_response.count() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" input_token = response.parse() assert_matches_type(InputTokenCountResponse, input_token, path=["response"]) @parametrize def test_streaming_response_count(self, client: OpenAI) -> None: with client.responses.input_tokens.with_streaming_response.count() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" input_token = response.parse() assert_matches_type(InputTokenCountResponse, input_token, path=["response"]) assert cast(Any, response.is_closed) is True class TestAsyncInputTokens: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_count(self, async_client: AsyncOpenAI) -> None: input_token = await async_client.responses.input_tokens.count() assert_matches_type(InputTokenCountResponse, input_token, path=["response"]) @parametrize async def test_method_count_with_all_params(self, async_client: AsyncOpenAI) -> None: input_token = await async_client.responses.input_tokens.count( conversation="string", input="string", instructions="instructions", model="model", parallel_tool_calls=True, previous_response_id="resp_123", reasoning={ "effort": "none", "generate_summary": "auto", "summary": "auto", }, text={ "format": {"type": "text"}, "verbosity": "low", }, tool_choice="none", tools=[ { "name": "name", "parameters": {"foo": "bar"}, "strict": True, "type": "function", "defer_loading": True, "description": "description", } ], truncation="auto", ) assert_matches_type(InputTokenCountResponse, input_token, path=["response"]) @parametrize async def test_raw_response_count(self, async_client: AsyncOpenAI) -> None: response = await async_client.responses.input_tokens.with_raw_response.count() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" input_token = response.parse() assert_matches_type(InputTokenCountResponse, input_token, path=["response"]) @parametrize async def test_streaming_response_count(self, async_client: AsyncOpenAI) -> None: async with async_client.responses.input_tokens.with_streaming_response.count() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" input_token = await response.parse() assert_matches_type(InputTokenCountResponse, input_token, path=["response"]) assert cast(Any, response.is_closed) is True ================================================ FILE: tests/api_resources/skills/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/skills/test_content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import httpx import pytest from respx import MockRouter import openai._legacy_response as _legacy_response from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type # pyright: reportDeprecated=false base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestContent: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize @pytest.mark.respx(base_url=base_url) def test_method_retrieve(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/skills/skill_123/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) content = client.skills.content.retrieve( "skill_123", ) assert isinstance(content, _legacy_response.HttpxBinaryResponseContent) assert content.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) def test_raw_response_retrieve(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/skills/skill_123/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = client.skills.content.with_raw_response.retrieve( "skill_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" content = response.parse() assert_matches_type(_legacy_response.HttpxBinaryResponseContent, content, path=["response"]) @parametrize @pytest.mark.respx(base_url=base_url) def test_streaming_response_retrieve(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/skills/skill_123/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) with client.skills.content.with_streaming_response.retrieve( "skill_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" content = response.parse() assert_matches_type(bytes, content, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize @pytest.mark.respx(base_url=base_url) def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `skill_id` but received ''"): client.skills.content.with_raw_response.retrieve( "", ) class TestAsyncContent: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize @pytest.mark.respx(base_url=base_url) async def test_method_retrieve(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/skills/skill_123/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) content = await async_client.skills.content.retrieve( "skill_123", ) assert isinstance(content, _legacy_response.HttpxBinaryResponseContent) assert content.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) async def test_raw_response_retrieve(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/skills/skill_123/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = await async_client.skills.content.with_raw_response.retrieve( "skill_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" content = response.parse() assert_matches_type(_legacy_response.HttpxBinaryResponseContent, content, path=["response"]) @parametrize @pytest.mark.respx(base_url=base_url) async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/skills/skill_123/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) async with async_client.skills.content.with_streaming_response.retrieve( "skill_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" content = await response.parse() assert_matches_type(bytes, content, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize @pytest.mark.respx(base_url=base_url) async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `skill_id` but received ''"): await async_client.skills.content.with_raw_response.retrieve( "", ) ================================================ FILE: tests/api_resources/skills/test_versions.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.pagination import SyncCursorPage, AsyncCursorPage from openai.types.skills import SkillVersion, DeletedSkillVersion base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestVersions: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: version = client.skills.versions.create( skill_id="skill_123", ) assert_matches_type(SkillVersion, version, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: version = client.skills.versions.create( skill_id="skill_123", default=True, files=[b"Example data"], ) assert_matches_type(SkillVersion, version, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.skills.versions.with_raw_response.create( skill_id="skill_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() assert_matches_type(SkillVersion, version, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.skills.versions.with_streaming_response.create( skill_id="skill_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() assert_matches_type(SkillVersion, version, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_create(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `skill_id` but received ''"): client.skills.versions.with_raw_response.create( skill_id="", ) @parametrize def test_method_retrieve(self, client: OpenAI) -> None: version = client.skills.versions.retrieve( version="version", skill_id="skill_123", ) assert_matches_type(SkillVersion, version, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: response = client.skills.versions.with_raw_response.retrieve( version="version", skill_id="skill_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() assert_matches_type(SkillVersion, version, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with client.skills.versions.with_streaming_response.retrieve( version="version", skill_id="skill_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() assert_matches_type(SkillVersion, version, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `skill_id` but received ''"): client.skills.versions.with_raw_response.retrieve( version="version", skill_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `version` but received ''"): client.skills.versions.with_raw_response.retrieve( version="", skill_id="skill_123", ) @parametrize def test_method_list(self, client: OpenAI) -> None: version = client.skills.versions.list( skill_id="skill_123", ) assert_matches_type(SyncCursorPage[SkillVersion], version, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: version = client.skills.versions.list( skill_id="skill_123", after="skillver_123", limit=0, order="asc", ) assert_matches_type(SyncCursorPage[SkillVersion], version, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.skills.versions.with_raw_response.list( skill_id="skill_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() assert_matches_type(SyncCursorPage[SkillVersion], version, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.skills.versions.with_streaming_response.list( skill_id="skill_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() assert_matches_type(SyncCursorPage[SkillVersion], version, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_list(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `skill_id` but received ''"): client.skills.versions.with_raw_response.list( skill_id="", ) @parametrize def test_method_delete(self, client: OpenAI) -> None: version = client.skills.versions.delete( version="version", skill_id="skill_123", ) assert_matches_type(DeletedSkillVersion, version, path=["response"]) @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: response = client.skills.versions.with_raw_response.delete( version="version", skill_id="skill_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() assert_matches_type(DeletedSkillVersion, version, path=["response"]) @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with client.skills.versions.with_streaming_response.delete( version="version", skill_id="skill_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() assert_matches_type(DeletedSkillVersion, version, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `skill_id` but received ''"): client.skills.versions.with_raw_response.delete( version="version", skill_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `version` but received ''"): client.skills.versions.with_raw_response.delete( version="", skill_id="skill_123", ) class TestAsyncVersions: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: version = await async_client.skills.versions.create( skill_id="skill_123", ) assert_matches_type(SkillVersion, version, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: version = await async_client.skills.versions.create( skill_id="skill_123", default=True, files=[b"Example data"], ) assert_matches_type(SkillVersion, version, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.skills.versions.with_raw_response.create( skill_id="skill_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() assert_matches_type(SkillVersion, version, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.skills.versions.with_streaming_response.create( skill_id="skill_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = await response.parse() assert_matches_type(SkillVersion, version, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_create(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `skill_id` but received ''"): await async_client.skills.versions.with_raw_response.create( skill_id="", ) @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: version = await async_client.skills.versions.retrieve( version="version", skill_id="skill_123", ) assert_matches_type(SkillVersion, version, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: response = await async_client.skills.versions.with_raw_response.retrieve( version="version", skill_id="skill_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() assert_matches_type(SkillVersion, version, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: async with async_client.skills.versions.with_streaming_response.retrieve( version="version", skill_id="skill_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = await response.parse() assert_matches_type(SkillVersion, version, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `skill_id` but received ''"): await async_client.skills.versions.with_raw_response.retrieve( version="version", skill_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `version` but received ''"): await async_client.skills.versions.with_raw_response.retrieve( version="", skill_id="skill_123", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: version = await async_client.skills.versions.list( skill_id="skill_123", ) assert_matches_type(AsyncCursorPage[SkillVersion], version, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: version = await async_client.skills.versions.list( skill_id="skill_123", after="skillver_123", limit=0, order="asc", ) assert_matches_type(AsyncCursorPage[SkillVersion], version, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.skills.versions.with_raw_response.list( skill_id="skill_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() assert_matches_type(AsyncCursorPage[SkillVersion], version, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.skills.versions.with_streaming_response.list( skill_id="skill_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = await response.parse() assert_matches_type(AsyncCursorPage[SkillVersion], version, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_list(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `skill_id` but received ''"): await async_client.skills.versions.with_raw_response.list( skill_id="", ) @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: version = await async_client.skills.versions.delete( version="version", skill_id="skill_123", ) assert_matches_type(DeletedSkillVersion, version, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: response = await async_client.skills.versions.with_raw_response.delete( version="version", skill_id="skill_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() assert_matches_type(DeletedSkillVersion, version, path=["response"]) @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: async with async_client.skills.versions.with_streaming_response.delete( version="version", skill_id="skill_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = await response.parse() assert_matches_type(DeletedSkillVersion, version, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `skill_id` but received ''"): await async_client.skills.versions.with_raw_response.delete( version="version", skill_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `version` but received ''"): await async_client.skills.versions.with_raw_response.delete( version="", skill_id="skill_123", ) ================================================ FILE: tests/api_resources/skills/versions/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/skills/versions/test_content.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import httpx import pytest from respx import MockRouter import openai._legacy_response as _legacy_response from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type # pyright: reportDeprecated=false base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestContent: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize @pytest.mark.respx(base_url=base_url) def test_method_retrieve(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/skills/skill_123/versions/version/content").mock( return_value=httpx.Response(200, json={"foo": "bar"}) ) content = client.skills.versions.content.retrieve( version="version", skill_id="skill_123", ) assert isinstance(content, _legacy_response.HttpxBinaryResponseContent) assert content.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) def test_raw_response_retrieve(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/skills/skill_123/versions/version/content").mock( return_value=httpx.Response(200, json={"foo": "bar"}) ) response = client.skills.versions.content.with_raw_response.retrieve( version="version", skill_id="skill_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" content = response.parse() assert_matches_type(_legacy_response.HttpxBinaryResponseContent, content, path=["response"]) @parametrize @pytest.mark.respx(base_url=base_url) def test_streaming_response_retrieve(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/skills/skill_123/versions/version/content").mock( return_value=httpx.Response(200, json={"foo": "bar"}) ) with client.skills.versions.content.with_streaming_response.retrieve( version="version", skill_id="skill_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" content = response.parse() assert_matches_type(bytes, content, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize @pytest.mark.respx(base_url=base_url) def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `skill_id` but received ''"): client.skills.versions.content.with_raw_response.retrieve( version="version", skill_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `version` but received ''"): client.skills.versions.content.with_raw_response.retrieve( version="", skill_id="skill_123", ) class TestAsyncContent: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize @pytest.mark.respx(base_url=base_url) async def test_method_retrieve(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/skills/skill_123/versions/version/content").mock( return_value=httpx.Response(200, json={"foo": "bar"}) ) content = await async_client.skills.versions.content.retrieve( version="version", skill_id="skill_123", ) assert isinstance(content, _legacy_response.HttpxBinaryResponseContent) assert content.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) async def test_raw_response_retrieve(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/skills/skill_123/versions/version/content").mock( return_value=httpx.Response(200, json={"foo": "bar"}) ) response = await async_client.skills.versions.content.with_raw_response.retrieve( version="version", skill_id="skill_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" content = response.parse() assert_matches_type(_legacy_response.HttpxBinaryResponseContent, content, path=["response"]) @parametrize @pytest.mark.respx(base_url=base_url) async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/skills/skill_123/versions/version/content").mock( return_value=httpx.Response(200, json={"foo": "bar"}) ) async with async_client.skills.versions.content.with_streaming_response.retrieve( version="version", skill_id="skill_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" content = await response.parse() assert_matches_type(bytes, content, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize @pytest.mark.respx(base_url=base_url) async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `skill_id` but received ''"): await async_client.skills.versions.content.with_raw_response.retrieve( version="version", skill_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `version` but received ''"): await async_client.skills.versions.content.with_raw_response.retrieve( version="", skill_id="skill_123", ) ================================================ FILE: tests/api_resources/test_batches.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types import Batch from openai.pagination import SyncCursorPage, AsyncCursorPage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestBatches: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: batch = client.batches.create( completion_window="24h", endpoint="/v1/responses", input_file_id="string", ) assert_matches_type(Batch, batch, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: batch = client.batches.create( completion_window="24h", endpoint="/v1/responses", input_file_id="string", metadata={"foo": "string"}, output_expires_after={ "anchor": "created_at", "seconds": 3600, }, ) assert_matches_type(Batch, batch, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.batches.with_raw_response.create( completion_window="24h", endpoint="/v1/responses", input_file_id="string", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" batch = response.parse() assert_matches_type(Batch, batch, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.batches.with_streaming_response.create( completion_window="24h", endpoint="/v1/responses", input_file_id="string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" batch = response.parse() assert_matches_type(Batch, batch, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_retrieve(self, client: OpenAI) -> None: batch = client.batches.retrieve( "string", ) assert_matches_type(Batch, batch, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: response = client.batches.with_raw_response.retrieve( "string", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" batch = response.parse() assert_matches_type(Batch, batch, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with client.batches.with_streaming_response.retrieve( "string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" batch = response.parse() assert_matches_type(Batch, batch, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `batch_id` but received ''"): client.batches.with_raw_response.retrieve( "", ) @parametrize def test_method_list(self, client: OpenAI) -> None: batch = client.batches.list() assert_matches_type(SyncCursorPage[Batch], batch, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: batch = client.batches.list( after="string", limit=0, ) assert_matches_type(SyncCursorPage[Batch], batch, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.batches.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" batch = response.parse() assert_matches_type(SyncCursorPage[Batch], batch, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.batches.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" batch = response.parse() assert_matches_type(SyncCursorPage[Batch], batch, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_cancel(self, client: OpenAI) -> None: batch = client.batches.cancel( "string", ) assert_matches_type(Batch, batch, path=["response"]) @parametrize def test_raw_response_cancel(self, client: OpenAI) -> None: response = client.batches.with_raw_response.cancel( "string", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" batch = response.parse() assert_matches_type(Batch, batch, path=["response"]) @parametrize def test_streaming_response_cancel(self, client: OpenAI) -> None: with client.batches.with_streaming_response.cancel( "string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" batch = response.parse() assert_matches_type(Batch, batch, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_cancel(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `batch_id` but received ''"): client.batches.with_raw_response.cancel( "", ) class TestAsyncBatches: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: batch = await async_client.batches.create( completion_window="24h", endpoint="/v1/responses", input_file_id="string", ) assert_matches_type(Batch, batch, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: batch = await async_client.batches.create( completion_window="24h", endpoint="/v1/responses", input_file_id="string", metadata={"foo": "string"}, output_expires_after={ "anchor": "created_at", "seconds": 3600, }, ) assert_matches_type(Batch, batch, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.batches.with_raw_response.create( completion_window="24h", endpoint="/v1/responses", input_file_id="string", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" batch = response.parse() assert_matches_type(Batch, batch, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.batches.with_streaming_response.create( completion_window="24h", endpoint="/v1/responses", input_file_id="string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" batch = await response.parse() assert_matches_type(Batch, batch, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: batch = await async_client.batches.retrieve( "string", ) assert_matches_type(Batch, batch, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: response = await async_client.batches.with_raw_response.retrieve( "string", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" batch = response.parse() assert_matches_type(Batch, batch, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: async with async_client.batches.with_streaming_response.retrieve( "string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" batch = await response.parse() assert_matches_type(Batch, batch, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `batch_id` but received ''"): await async_client.batches.with_raw_response.retrieve( "", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: batch = await async_client.batches.list() assert_matches_type(AsyncCursorPage[Batch], batch, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: batch = await async_client.batches.list( after="string", limit=0, ) assert_matches_type(AsyncCursorPage[Batch], batch, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.batches.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" batch = response.parse() assert_matches_type(AsyncCursorPage[Batch], batch, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.batches.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" batch = await response.parse() assert_matches_type(AsyncCursorPage[Batch], batch, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_cancel(self, async_client: AsyncOpenAI) -> None: batch = await async_client.batches.cancel( "string", ) assert_matches_type(Batch, batch, path=["response"]) @parametrize async def test_raw_response_cancel(self, async_client: AsyncOpenAI) -> None: response = await async_client.batches.with_raw_response.cancel( "string", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" batch = response.parse() assert_matches_type(Batch, batch, path=["response"]) @parametrize async def test_streaming_response_cancel(self, async_client: AsyncOpenAI) -> None: async with async_client.batches.with_streaming_response.cancel( "string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" batch = await response.parse() assert_matches_type(Batch, batch, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_cancel(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `batch_id` but received ''"): await async_client.batches.with_raw_response.cancel( "", ) ================================================ FILE: tests/api_resources/test_completions.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types import Completion base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestCompletions: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create_overload_1(self, client: OpenAI) -> None: completion = client.completions.create( model="string", prompt="This is a test.", ) assert_matches_type(Completion, completion, path=["response"]) @parametrize def test_method_create_with_all_params_overload_1(self, client: OpenAI) -> None: completion = client.completions.create( model="string", prompt="This is a test.", best_of=0, echo=True, frequency_penalty=-2, logit_bias={"foo": 0}, logprobs=0, max_tokens=16, n=1, presence_penalty=-2, seed=0, stop="\n", stream=False, stream_options={ "include_obfuscation": True, "include_usage": True, }, suffix="test.", temperature=1, top_p=1, user="user-1234", ) assert_matches_type(Completion, completion, path=["response"]) @parametrize def test_raw_response_create_overload_1(self, client: OpenAI) -> None: response = client.completions.with_raw_response.create( model="string", prompt="This is a test.", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = response.parse() assert_matches_type(Completion, completion, path=["response"]) @parametrize def test_streaming_response_create_overload_1(self, client: OpenAI) -> None: with client.completions.with_streaming_response.create( model="string", prompt="This is a test.", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = response.parse() assert_matches_type(Completion, completion, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_create_overload_2(self, client: OpenAI) -> None: completion_stream = client.completions.create( model="string", prompt="This is a test.", stream=True, ) completion_stream.response.close() @parametrize def test_method_create_with_all_params_overload_2(self, client: OpenAI) -> None: completion_stream = client.completions.create( model="string", prompt="This is a test.", stream=True, best_of=0, echo=True, frequency_penalty=-2, logit_bias={"foo": 0}, logprobs=0, max_tokens=16, n=1, presence_penalty=-2, seed=0, stop="\n", stream_options={ "include_obfuscation": True, "include_usage": True, }, suffix="test.", temperature=1, top_p=1, user="user-1234", ) completion_stream.response.close() @parametrize def test_raw_response_create_overload_2(self, client: OpenAI) -> None: response = client.completions.with_raw_response.create( model="string", prompt="This is a test.", stream=True, ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() @parametrize def test_streaming_response_create_overload_2(self, client: OpenAI) -> None: with client.completions.with_streaming_response.create( model="string", prompt="This is a test.", stream=True, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() assert cast(Any, response.is_closed) is True class TestAsyncCompletions: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create_overload_1(self, async_client: AsyncOpenAI) -> None: completion = await async_client.completions.create( model="string", prompt="This is a test.", ) assert_matches_type(Completion, completion, path=["response"]) @parametrize async def test_method_create_with_all_params_overload_1(self, async_client: AsyncOpenAI) -> None: completion = await async_client.completions.create( model="string", prompt="This is a test.", best_of=0, echo=True, frequency_penalty=-2, logit_bias={"foo": 0}, logprobs=0, max_tokens=16, n=1, presence_penalty=-2, seed=0, stop="\n", stream=False, stream_options={ "include_obfuscation": True, "include_usage": True, }, suffix="test.", temperature=1, top_p=1, user="user-1234", ) assert_matches_type(Completion, completion, path=["response"]) @parametrize async def test_raw_response_create_overload_1(self, async_client: AsyncOpenAI) -> None: response = await async_client.completions.with_raw_response.create( model="string", prompt="This is a test.", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = response.parse() assert_matches_type(Completion, completion, path=["response"]) @parametrize async def test_streaming_response_create_overload_1(self, async_client: AsyncOpenAI) -> None: async with async_client.completions.with_streaming_response.create( model="string", prompt="This is a test.", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" completion = await response.parse() assert_matches_type(Completion, completion, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_create_overload_2(self, async_client: AsyncOpenAI) -> None: completion_stream = await async_client.completions.create( model="string", prompt="This is a test.", stream=True, ) await completion_stream.response.aclose() @parametrize async def test_method_create_with_all_params_overload_2(self, async_client: AsyncOpenAI) -> None: completion_stream = await async_client.completions.create( model="string", prompt="This is a test.", stream=True, best_of=0, echo=True, frequency_penalty=-2, logit_bias={"foo": 0}, logprobs=0, max_tokens=16, n=1, presence_penalty=-2, seed=0, stop="\n", stream_options={ "include_obfuscation": True, "include_usage": True, }, suffix="test.", temperature=1, top_p=1, user="user-1234", ) await completion_stream.response.aclose() @parametrize async def test_raw_response_create_overload_2(self, async_client: AsyncOpenAI) -> None: response = await async_client.completions.with_raw_response.create( model="string", prompt="This is a test.", stream=True, ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() await stream.close() @parametrize async def test_streaming_response_create_overload_2(self, async_client: AsyncOpenAI) -> None: async with async_client.completions.with_streaming_response.create( model="string", prompt="This is a test.", stream=True, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = await response.parse() await stream.close() assert cast(Any, response.is_closed) is True ================================================ FILE: tests/api_resources/test_containers.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types import ( ContainerListResponse, ContainerCreateResponse, ContainerRetrieveResponse, ) from openai.pagination import SyncCursorPage, AsyncCursorPage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestContainers: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: container = client.containers.create( name="name", ) assert_matches_type(ContainerCreateResponse, container, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: container = client.containers.create( name="name", expires_after={ "anchor": "last_active_at", "minutes": 0, }, file_ids=["string"], memory_limit="1g", network_policy={"type": "disabled"}, skills=[ { "skill_id": "x", "type": "skill_reference", "version": "version", } ], ) assert_matches_type(ContainerCreateResponse, container, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.containers.with_raw_response.create( name="name", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" container = response.parse() assert_matches_type(ContainerCreateResponse, container, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.containers.with_streaming_response.create( name="name", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" container = response.parse() assert_matches_type(ContainerCreateResponse, container, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_retrieve(self, client: OpenAI) -> None: container = client.containers.retrieve( "container_id", ) assert_matches_type(ContainerRetrieveResponse, container, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: response = client.containers.with_raw_response.retrieve( "container_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" container = response.parse() assert_matches_type(ContainerRetrieveResponse, container, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with client.containers.with_streaming_response.retrieve( "container_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" container = response.parse() assert_matches_type(ContainerRetrieveResponse, container, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `container_id` but received ''"): client.containers.with_raw_response.retrieve( "", ) @parametrize def test_method_list(self, client: OpenAI) -> None: container = client.containers.list() assert_matches_type(SyncCursorPage[ContainerListResponse], container, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: container = client.containers.list( after="after", limit=0, name="name", order="asc", ) assert_matches_type(SyncCursorPage[ContainerListResponse], container, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.containers.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" container = response.parse() assert_matches_type(SyncCursorPage[ContainerListResponse], container, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.containers.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" container = response.parse() assert_matches_type(SyncCursorPage[ContainerListResponse], container, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_delete(self, client: OpenAI) -> None: container = client.containers.delete( "container_id", ) assert container is None @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: response = client.containers.with_raw_response.delete( "container_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" container = response.parse() assert container is None @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with client.containers.with_streaming_response.delete( "container_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" container = response.parse() assert container is None assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `container_id` but received ''"): client.containers.with_raw_response.delete( "", ) class TestAsyncContainers: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: container = await async_client.containers.create( name="name", ) assert_matches_type(ContainerCreateResponse, container, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: container = await async_client.containers.create( name="name", expires_after={ "anchor": "last_active_at", "minutes": 0, }, file_ids=["string"], memory_limit="1g", network_policy={"type": "disabled"}, skills=[ { "skill_id": "x", "type": "skill_reference", "version": "version", } ], ) assert_matches_type(ContainerCreateResponse, container, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.containers.with_raw_response.create( name="name", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" container = response.parse() assert_matches_type(ContainerCreateResponse, container, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.containers.with_streaming_response.create( name="name", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" container = await response.parse() assert_matches_type(ContainerCreateResponse, container, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: container = await async_client.containers.retrieve( "container_id", ) assert_matches_type(ContainerRetrieveResponse, container, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: response = await async_client.containers.with_raw_response.retrieve( "container_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" container = response.parse() assert_matches_type(ContainerRetrieveResponse, container, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: async with async_client.containers.with_streaming_response.retrieve( "container_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" container = await response.parse() assert_matches_type(ContainerRetrieveResponse, container, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `container_id` but received ''"): await async_client.containers.with_raw_response.retrieve( "", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: container = await async_client.containers.list() assert_matches_type(AsyncCursorPage[ContainerListResponse], container, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: container = await async_client.containers.list( after="after", limit=0, name="name", order="asc", ) assert_matches_type(AsyncCursorPage[ContainerListResponse], container, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.containers.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" container = response.parse() assert_matches_type(AsyncCursorPage[ContainerListResponse], container, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.containers.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" container = await response.parse() assert_matches_type(AsyncCursorPage[ContainerListResponse], container, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: container = await async_client.containers.delete( "container_id", ) assert container is None @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: response = await async_client.containers.with_raw_response.delete( "container_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" container = response.parse() assert container is None @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: async with async_client.containers.with_streaming_response.delete( "container_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" container = await response.parse() assert container is None assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `container_id` but received ''"): await async_client.containers.with_raw_response.delete( "", ) ================================================ FILE: tests/api_resources/test_conversations.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types.conversations import ( Conversation, ConversationDeletedResource, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestConversations: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: conversation = client.conversations.create() assert_matches_type(Conversation, conversation, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: conversation = client.conversations.create( items=[ { "content": "string", "role": "user", "phase": "commentary", "type": "message", } ], metadata={"foo": "string"}, ) assert_matches_type(Conversation, conversation, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.conversations.with_raw_response.create() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = response.parse() assert_matches_type(Conversation, conversation, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.conversations.with_streaming_response.create() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = response.parse() assert_matches_type(Conversation, conversation, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_retrieve(self, client: OpenAI) -> None: conversation = client.conversations.retrieve( "conv_123", ) assert_matches_type(Conversation, conversation, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: response = client.conversations.with_raw_response.retrieve( "conv_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = response.parse() assert_matches_type(Conversation, conversation, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with client.conversations.with_streaming_response.retrieve( "conv_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = response.parse() assert_matches_type(Conversation, conversation, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): client.conversations.with_raw_response.retrieve( "", ) @parametrize def test_method_update(self, client: OpenAI) -> None: conversation = client.conversations.update( conversation_id="conv_123", metadata={"foo": "string"}, ) assert_matches_type(Conversation, conversation, path=["response"]) @parametrize def test_raw_response_update(self, client: OpenAI) -> None: response = client.conversations.with_raw_response.update( conversation_id="conv_123", metadata={"foo": "string"}, ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = response.parse() assert_matches_type(Conversation, conversation, path=["response"]) @parametrize def test_streaming_response_update(self, client: OpenAI) -> None: with client.conversations.with_streaming_response.update( conversation_id="conv_123", metadata={"foo": "string"}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = response.parse() assert_matches_type(Conversation, conversation, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_update(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): client.conversations.with_raw_response.update( conversation_id="", metadata={"foo": "string"}, ) @parametrize def test_method_delete(self, client: OpenAI) -> None: conversation = client.conversations.delete( "conv_123", ) assert_matches_type(ConversationDeletedResource, conversation, path=["response"]) @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: response = client.conversations.with_raw_response.delete( "conv_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = response.parse() assert_matches_type(ConversationDeletedResource, conversation, path=["response"]) @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with client.conversations.with_streaming_response.delete( "conv_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = response.parse() assert_matches_type(ConversationDeletedResource, conversation, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): client.conversations.with_raw_response.delete( "", ) class TestAsyncConversations: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: conversation = await async_client.conversations.create() assert_matches_type(Conversation, conversation, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: conversation = await async_client.conversations.create( items=[ { "content": "string", "role": "user", "phase": "commentary", "type": "message", } ], metadata={"foo": "string"}, ) assert_matches_type(Conversation, conversation, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.conversations.with_raw_response.create() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = response.parse() assert_matches_type(Conversation, conversation, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.conversations.with_streaming_response.create() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = await response.parse() assert_matches_type(Conversation, conversation, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: conversation = await async_client.conversations.retrieve( "conv_123", ) assert_matches_type(Conversation, conversation, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: response = await async_client.conversations.with_raw_response.retrieve( "conv_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = response.parse() assert_matches_type(Conversation, conversation, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: async with async_client.conversations.with_streaming_response.retrieve( "conv_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = await response.parse() assert_matches_type(Conversation, conversation, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): await async_client.conversations.with_raw_response.retrieve( "", ) @parametrize async def test_method_update(self, async_client: AsyncOpenAI) -> None: conversation = await async_client.conversations.update( conversation_id="conv_123", metadata={"foo": "string"}, ) assert_matches_type(Conversation, conversation, path=["response"]) @parametrize async def test_raw_response_update(self, async_client: AsyncOpenAI) -> None: response = await async_client.conversations.with_raw_response.update( conversation_id="conv_123", metadata={"foo": "string"}, ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = response.parse() assert_matches_type(Conversation, conversation, path=["response"]) @parametrize async def test_streaming_response_update(self, async_client: AsyncOpenAI) -> None: async with async_client.conversations.with_streaming_response.update( conversation_id="conv_123", metadata={"foo": "string"}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = await response.parse() assert_matches_type(Conversation, conversation, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_update(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): await async_client.conversations.with_raw_response.update( conversation_id="", metadata={"foo": "string"}, ) @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: conversation = await async_client.conversations.delete( "conv_123", ) assert_matches_type(ConversationDeletedResource, conversation, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: response = await async_client.conversations.with_raw_response.delete( "conv_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = response.parse() assert_matches_type(ConversationDeletedResource, conversation, path=["response"]) @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: async with async_client.conversations.with_streaming_response.delete( "conv_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" conversation = await response.parse() assert_matches_type(ConversationDeletedResource, conversation, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): await async_client.conversations.with_raw_response.delete( "", ) ================================================ FILE: tests/api_resources/test_embeddings.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types import CreateEmbeddingResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestEmbeddings: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: embedding = client.embeddings.create( input="The quick brown fox jumped over the lazy dog", model="text-embedding-3-small", ) assert_matches_type(CreateEmbeddingResponse, embedding, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: embedding = client.embeddings.create( input="The quick brown fox jumped over the lazy dog", model="text-embedding-3-small", dimensions=1, encoding_format="float", user="user-1234", ) assert_matches_type(CreateEmbeddingResponse, embedding, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.embeddings.with_raw_response.create( input="The quick brown fox jumped over the lazy dog", model="text-embedding-3-small", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" embedding = response.parse() assert_matches_type(CreateEmbeddingResponse, embedding, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.embeddings.with_streaming_response.create( input="The quick brown fox jumped over the lazy dog", model="text-embedding-3-small", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" embedding = response.parse() assert_matches_type(CreateEmbeddingResponse, embedding, path=["response"]) assert cast(Any, response.is_closed) is True class TestAsyncEmbeddings: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: embedding = await async_client.embeddings.create( input="The quick brown fox jumped over the lazy dog", model="text-embedding-3-small", ) assert_matches_type(CreateEmbeddingResponse, embedding, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: embedding = await async_client.embeddings.create( input="The quick brown fox jumped over the lazy dog", model="text-embedding-3-small", dimensions=1, encoding_format="float", user="user-1234", ) assert_matches_type(CreateEmbeddingResponse, embedding, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.embeddings.with_raw_response.create( input="The quick brown fox jumped over the lazy dog", model="text-embedding-3-small", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" embedding = response.parse() assert_matches_type(CreateEmbeddingResponse, embedding, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.embeddings.with_streaming_response.create( input="The quick brown fox jumped over the lazy dog", model="text-embedding-3-small", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" embedding = await response.parse() assert_matches_type(CreateEmbeddingResponse, embedding, path=["response"]) assert cast(Any, response.is_closed) is True ================================================ FILE: tests/api_resources/test_evals.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types import ( EvalListResponse, EvalCreateResponse, EvalDeleteResponse, EvalUpdateResponse, EvalRetrieveResponse, ) from openai.pagination import SyncCursorPage, AsyncCursorPage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestEvals: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: eval = client.evals.create( data_source_config={ "item_schema": {"foo": "bar"}, "type": "custom", }, testing_criteria=[ { "input": [ { "content": "content", "role": "role", } ], "labels": ["string"], "model": "model", "name": "name", "passing_labels": ["string"], "type": "label_model", } ], ) assert_matches_type(EvalCreateResponse, eval, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: eval = client.evals.create( data_source_config={ "item_schema": {"foo": "bar"}, "type": "custom", "include_sample_schema": True, }, testing_criteria=[ { "input": [ { "content": "content", "role": "role", } ], "labels": ["string"], "model": "model", "name": "name", "passing_labels": ["string"], "type": "label_model", } ], metadata={"foo": "string"}, name="name", ) assert_matches_type(EvalCreateResponse, eval, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.evals.with_raw_response.create( data_source_config={ "item_schema": {"foo": "bar"}, "type": "custom", }, testing_criteria=[ { "input": [ { "content": "content", "role": "role", } ], "labels": ["string"], "model": "model", "name": "name", "passing_labels": ["string"], "type": "label_model", } ], ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = response.parse() assert_matches_type(EvalCreateResponse, eval, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.evals.with_streaming_response.create( data_source_config={ "item_schema": {"foo": "bar"}, "type": "custom", }, testing_criteria=[ { "input": [ { "content": "content", "role": "role", } ], "labels": ["string"], "model": "model", "name": "name", "passing_labels": ["string"], "type": "label_model", } ], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = response.parse() assert_matches_type(EvalCreateResponse, eval, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_retrieve(self, client: OpenAI) -> None: eval = client.evals.retrieve( "eval_id", ) assert_matches_type(EvalRetrieveResponse, eval, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: response = client.evals.with_raw_response.retrieve( "eval_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = response.parse() assert_matches_type(EvalRetrieveResponse, eval, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with client.evals.with_streaming_response.retrieve( "eval_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = response.parse() assert_matches_type(EvalRetrieveResponse, eval, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): client.evals.with_raw_response.retrieve( "", ) @parametrize def test_method_update(self, client: OpenAI) -> None: eval = client.evals.update( eval_id="eval_id", ) assert_matches_type(EvalUpdateResponse, eval, path=["response"]) @parametrize def test_method_update_with_all_params(self, client: OpenAI) -> None: eval = client.evals.update( eval_id="eval_id", metadata={"foo": "string"}, name="name", ) assert_matches_type(EvalUpdateResponse, eval, path=["response"]) @parametrize def test_raw_response_update(self, client: OpenAI) -> None: response = client.evals.with_raw_response.update( eval_id="eval_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = response.parse() assert_matches_type(EvalUpdateResponse, eval, path=["response"]) @parametrize def test_streaming_response_update(self, client: OpenAI) -> None: with client.evals.with_streaming_response.update( eval_id="eval_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = response.parse() assert_matches_type(EvalUpdateResponse, eval, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_update(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): client.evals.with_raw_response.update( eval_id="", ) @parametrize def test_method_list(self, client: OpenAI) -> None: eval = client.evals.list() assert_matches_type(SyncCursorPage[EvalListResponse], eval, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: eval = client.evals.list( after="after", limit=0, order="asc", order_by="created_at", ) assert_matches_type(SyncCursorPage[EvalListResponse], eval, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.evals.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = response.parse() assert_matches_type(SyncCursorPage[EvalListResponse], eval, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.evals.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = response.parse() assert_matches_type(SyncCursorPage[EvalListResponse], eval, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_delete(self, client: OpenAI) -> None: eval = client.evals.delete( "eval_id", ) assert_matches_type(EvalDeleteResponse, eval, path=["response"]) @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: response = client.evals.with_raw_response.delete( "eval_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = response.parse() assert_matches_type(EvalDeleteResponse, eval, path=["response"]) @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with client.evals.with_streaming_response.delete( "eval_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = response.parse() assert_matches_type(EvalDeleteResponse, eval, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): client.evals.with_raw_response.delete( "", ) class TestAsyncEvals: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: eval = await async_client.evals.create( data_source_config={ "item_schema": {"foo": "bar"}, "type": "custom", }, testing_criteria=[ { "input": [ { "content": "content", "role": "role", } ], "labels": ["string"], "model": "model", "name": "name", "passing_labels": ["string"], "type": "label_model", } ], ) assert_matches_type(EvalCreateResponse, eval, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: eval = await async_client.evals.create( data_source_config={ "item_schema": {"foo": "bar"}, "type": "custom", "include_sample_schema": True, }, testing_criteria=[ { "input": [ { "content": "content", "role": "role", } ], "labels": ["string"], "model": "model", "name": "name", "passing_labels": ["string"], "type": "label_model", } ], metadata={"foo": "string"}, name="name", ) assert_matches_type(EvalCreateResponse, eval, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.evals.with_raw_response.create( data_source_config={ "item_schema": {"foo": "bar"}, "type": "custom", }, testing_criteria=[ { "input": [ { "content": "content", "role": "role", } ], "labels": ["string"], "model": "model", "name": "name", "passing_labels": ["string"], "type": "label_model", } ], ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = response.parse() assert_matches_type(EvalCreateResponse, eval, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.evals.with_streaming_response.create( data_source_config={ "item_schema": {"foo": "bar"}, "type": "custom", }, testing_criteria=[ { "input": [ { "content": "content", "role": "role", } ], "labels": ["string"], "model": "model", "name": "name", "passing_labels": ["string"], "type": "label_model", } ], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = await response.parse() assert_matches_type(EvalCreateResponse, eval, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: eval = await async_client.evals.retrieve( "eval_id", ) assert_matches_type(EvalRetrieveResponse, eval, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: response = await async_client.evals.with_raw_response.retrieve( "eval_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = response.parse() assert_matches_type(EvalRetrieveResponse, eval, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: async with async_client.evals.with_streaming_response.retrieve( "eval_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = await response.parse() assert_matches_type(EvalRetrieveResponse, eval, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): await async_client.evals.with_raw_response.retrieve( "", ) @parametrize async def test_method_update(self, async_client: AsyncOpenAI) -> None: eval = await async_client.evals.update( eval_id="eval_id", ) assert_matches_type(EvalUpdateResponse, eval, path=["response"]) @parametrize async def test_method_update_with_all_params(self, async_client: AsyncOpenAI) -> None: eval = await async_client.evals.update( eval_id="eval_id", metadata={"foo": "string"}, name="name", ) assert_matches_type(EvalUpdateResponse, eval, path=["response"]) @parametrize async def test_raw_response_update(self, async_client: AsyncOpenAI) -> None: response = await async_client.evals.with_raw_response.update( eval_id="eval_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = response.parse() assert_matches_type(EvalUpdateResponse, eval, path=["response"]) @parametrize async def test_streaming_response_update(self, async_client: AsyncOpenAI) -> None: async with async_client.evals.with_streaming_response.update( eval_id="eval_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = await response.parse() assert_matches_type(EvalUpdateResponse, eval, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_update(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): await async_client.evals.with_raw_response.update( eval_id="", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: eval = await async_client.evals.list() assert_matches_type(AsyncCursorPage[EvalListResponse], eval, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: eval = await async_client.evals.list( after="after", limit=0, order="asc", order_by="created_at", ) assert_matches_type(AsyncCursorPage[EvalListResponse], eval, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.evals.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = response.parse() assert_matches_type(AsyncCursorPage[EvalListResponse], eval, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.evals.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = await response.parse() assert_matches_type(AsyncCursorPage[EvalListResponse], eval, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: eval = await async_client.evals.delete( "eval_id", ) assert_matches_type(EvalDeleteResponse, eval, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: response = await async_client.evals.with_raw_response.delete( "eval_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = response.parse() assert_matches_type(EvalDeleteResponse, eval, path=["response"]) @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: async with async_client.evals.with_streaming_response.delete( "eval_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" eval = await response.parse() assert_matches_type(EvalDeleteResponse, eval, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `eval_id` but received ''"): await async_client.evals.with_raw_response.delete( "", ) ================================================ FILE: tests/api_resources/test_files.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import httpx import pytest from respx import MockRouter import openai._legacy_response as _legacy_response from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types import FileObject, FileDeleted from openai.pagination import SyncCursorPage, AsyncCursorPage # pyright: reportDeprecated=false base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestFiles: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: file = client.files.create( file=b"Example data", purpose="assistants", ) assert_matches_type(FileObject, file, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: file = client.files.create( file=b"Example data", purpose="assistants", expires_after={ "anchor": "created_at", "seconds": 3600, }, ) assert_matches_type(FileObject, file, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.files.with_raw_response.create( file=b"Example data", purpose="assistants", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(FileObject, file, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.files.with_streaming_response.create( file=b"Example data", purpose="assistants", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(FileObject, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_retrieve(self, client: OpenAI) -> None: file = client.files.retrieve( "string", ) assert_matches_type(FileObject, file, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: response = client.files.with_raw_response.retrieve( "string", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(FileObject, file, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with client.files.with_streaming_response.retrieve( "string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(FileObject, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): client.files.with_raw_response.retrieve( "", ) @parametrize def test_method_list(self, client: OpenAI) -> None: file = client.files.list() assert_matches_type(SyncCursorPage[FileObject], file, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: file = client.files.list( after="after", limit=0, order="asc", purpose="purpose", ) assert_matches_type(SyncCursorPage[FileObject], file, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.files.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(SyncCursorPage[FileObject], file, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.files.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(SyncCursorPage[FileObject], file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_delete(self, client: OpenAI) -> None: file = client.files.delete( "string", ) assert_matches_type(FileDeleted, file, path=["response"]) @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: response = client.files.with_raw_response.delete( "string", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(FileDeleted, file, path=["response"]) @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with client.files.with_streaming_response.delete( "string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(FileDeleted, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): client.files.with_raw_response.delete( "", ) @parametrize @pytest.mark.respx(base_url=base_url) def test_method_content(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/files/string/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) file = client.files.content( "string", ) assert isinstance(file, _legacy_response.HttpxBinaryResponseContent) assert file.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) def test_raw_response_content(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/files/string/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = client.files.with_raw_response.content( "string", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(_legacy_response.HttpxBinaryResponseContent, file, path=["response"]) @parametrize @pytest.mark.respx(base_url=base_url) def test_streaming_response_content(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/files/string/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) with client.files.with_streaming_response.content( "string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(bytes, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize @pytest.mark.respx(base_url=base_url) def test_path_params_content(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): client.files.with_raw_response.content( "", ) @parametrize def test_method_retrieve_content(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): file = client.files.retrieve_content( "string", ) assert_matches_type(str, file, path=["response"]) @parametrize def test_raw_response_retrieve_content(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): response = client.files.with_raw_response.retrieve_content( "string", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(str, file, path=["response"]) @parametrize def test_streaming_response_retrieve_content(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with client.files.with_streaming_response.retrieve_content( "string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(str, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve_content(self, client: OpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): client.files.with_raw_response.retrieve_content( "", ) class TestAsyncFiles: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: file = await async_client.files.create( file=b"Example data", purpose="assistants", ) assert_matches_type(FileObject, file, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: file = await async_client.files.create( file=b"Example data", purpose="assistants", expires_after={ "anchor": "created_at", "seconds": 3600, }, ) assert_matches_type(FileObject, file, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.files.with_raw_response.create( file=b"Example data", purpose="assistants", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(FileObject, file, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.files.with_streaming_response.create( file=b"Example data", purpose="assistants", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() assert_matches_type(FileObject, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: file = await async_client.files.retrieve( "string", ) assert_matches_type(FileObject, file, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: response = await async_client.files.with_raw_response.retrieve( "string", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(FileObject, file, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: async with async_client.files.with_streaming_response.retrieve( "string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() assert_matches_type(FileObject, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): await async_client.files.with_raw_response.retrieve( "", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: file = await async_client.files.list() assert_matches_type(AsyncCursorPage[FileObject], file, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: file = await async_client.files.list( after="after", limit=0, order="asc", purpose="purpose", ) assert_matches_type(AsyncCursorPage[FileObject], file, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.files.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(AsyncCursorPage[FileObject], file, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.files.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() assert_matches_type(AsyncCursorPage[FileObject], file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: file = await async_client.files.delete( "string", ) assert_matches_type(FileDeleted, file, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: response = await async_client.files.with_raw_response.delete( "string", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(FileDeleted, file, path=["response"]) @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: async with async_client.files.with_streaming_response.delete( "string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() assert_matches_type(FileDeleted, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): await async_client.files.with_raw_response.delete( "", ) @parametrize @pytest.mark.respx(base_url=base_url) async def test_method_content(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/files/string/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) file = await async_client.files.content( "string", ) assert isinstance(file, _legacy_response.HttpxBinaryResponseContent) assert file.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) async def test_raw_response_content(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/files/string/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = await async_client.files.with_raw_response.content( "string", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(_legacy_response.HttpxBinaryResponseContent, file, path=["response"]) @parametrize @pytest.mark.respx(base_url=base_url) async def test_streaming_response_content(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/files/string/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) async with async_client.files.with_streaming_response.content( "string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() assert_matches_type(bytes, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize @pytest.mark.respx(base_url=base_url) async def test_path_params_content(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): await async_client.files.with_raw_response.content( "", ) @parametrize async def test_method_retrieve_content(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): file = await async_client.files.retrieve_content( "string", ) assert_matches_type(str, file, path=["response"]) @parametrize async def test_raw_response_retrieve_content(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): response = await async_client.files.with_raw_response.retrieve_content( "string", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(str, file, path=["response"]) @parametrize async def test_streaming_response_retrieve_content(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): async with async_client.files.with_streaming_response.retrieve_content( "string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() assert_matches_type(str, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve_content(self, async_client: AsyncOpenAI) -> None: with pytest.warns(DeprecationWarning): with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): await async_client.files.with_raw_response.retrieve_content( "", ) ================================================ FILE: tests/api_resources/test_images.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types import ImagesResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestImages: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create_variation(self, client: OpenAI) -> None: image = client.images.create_variation( image=b"Example data", ) assert_matches_type(ImagesResponse, image, path=["response"]) @parametrize def test_method_create_variation_with_all_params(self, client: OpenAI) -> None: image = client.images.create_variation( image=b"Example data", model="string", n=1, response_format="url", size="1024x1024", user="user-1234", ) assert_matches_type(ImagesResponse, image, path=["response"]) @parametrize def test_raw_response_create_variation(self, client: OpenAI) -> None: response = client.images.with_raw_response.create_variation( image=b"Example data", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" image = response.parse() assert_matches_type(ImagesResponse, image, path=["response"]) @parametrize def test_streaming_response_create_variation(self, client: OpenAI) -> None: with client.images.with_streaming_response.create_variation( image=b"Example data", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" image = response.parse() assert_matches_type(ImagesResponse, image, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_edit_overload_1(self, client: OpenAI) -> None: image = client.images.edit( image=b"Example data", prompt="A cute baby sea otter wearing a beret", ) assert_matches_type(ImagesResponse, image, path=["response"]) @parametrize def test_method_edit_with_all_params_overload_1(self, client: OpenAI) -> None: image = client.images.edit( image=b"Example data", prompt="A cute baby sea otter wearing a beret", background="transparent", input_fidelity="high", mask=b"Example data", model="string", n=1, output_compression=100, output_format="png", partial_images=1, quality="high", response_format="url", size="1024x1024", stream=False, user="user-1234", ) assert_matches_type(ImagesResponse, image, path=["response"]) @parametrize def test_raw_response_edit_overload_1(self, client: OpenAI) -> None: response = client.images.with_raw_response.edit( image=b"Example data", prompt="A cute baby sea otter wearing a beret", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" image = response.parse() assert_matches_type(ImagesResponse, image, path=["response"]) @parametrize def test_streaming_response_edit_overload_1(self, client: OpenAI) -> None: with client.images.with_streaming_response.edit( image=b"Example data", prompt="A cute baby sea otter wearing a beret", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" image = response.parse() assert_matches_type(ImagesResponse, image, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_edit_overload_2(self, client: OpenAI) -> None: image_stream = client.images.edit( image=b"Example data", prompt="A cute baby sea otter wearing a beret", stream=True, ) image_stream.response.close() @parametrize def test_method_edit_with_all_params_overload_2(self, client: OpenAI) -> None: image_stream = client.images.edit( image=b"Example data", prompt="A cute baby sea otter wearing a beret", stream=True, background="transparent", input_fidelity="high", mask=b"Example data", model="string", n=1, output_compression=100, output_format="png", partial_images=1, quality="high", response_format="url", size="1024x1024", user="user-1234", ) image_stream.response.close() @parametrize def test_raw_response_edit_overload_2(self, client: OpenAI) -> None: response = client.images.with_raw_response.edit( image=b"Example data", prompt="A cute baby sea otter wearing a beret", stream=True, ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() @parametrize def test_streaming_response_edit_overload_2(self, client: OpenAI) -> None: with client.images.with_streaming_response.edit( image=b"Example data", prompt="A cute baby sea otter wearing a beret", stream=True, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() assert cast(Any, response.is_closed) is True @parametrize def test_method_generate_overload_1(self, client: OpenAI) -> None: image = client.images.generate( prompt="A cute baby sea otter", ) assert_matches_type(ImagesResponse, image, path=["response"]) @parametrize def test_method_generate_with_all_params_overload_1(self, client: OpenAI) -> None: image = client.images.generate( prompt="A cute baby sea otter", background="transparent", model="string", moderation="low", n=1, output_compression=100, output_format="png", partial_images=1, quality="medium", response_format="url", size="1024x1024", stream=False, style="vivid", user="user-1234", ) assert_matches_type(ImagesResponse, image, path=["response"]) @parametrize def test_raw_response_generate_overload_1(self, client: OpenAI) -> None: response = client.images.with_raw_response.generate( prompt="A cute baby sea otter", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" image = response.parse() assert_matches_type(ImagesResponse, image, path=["response"]) @parametrize def test_streaming_response_generate_overload_1(self, client: OpenAI) -> None: with client.images.with_streaming_response.generate( prompt="A cute baby sea otter", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" image = response.parse() assert_matches_type(ImagesResponse, image, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_generate_overload_2(self, client: OpenAI) -> None: image_stream = client.images.generate( prompt="A cute baby sea otter", stream=True, ) image_stream.response.close() @parametrize def test_method_generate_with_all_params_overload_2(self, client: OpenAI) -> None: image_stream = client.images.generate( prompt="A cute baby sea otter", stream=True, background="transparent", model="string", moderation="low", n=1, output_compression=100, output_format="png", partial_images=1, quality="medium", response_format="url", size="1024x1024", style="vivid", user="user-1234", ) image_stream.response.close() @parametrize def test_raw_response_generate_overload_2(self, client: OpenAI) -> None: response = client.images.with_raw_response.generate( prompt="A cute baby sea otter", stream=True, ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() @parametrize def test_streaming_response_generate_overload_2(self, client: OpenAI) -> None: with client.images.with_streaming_response.generate( prompt="A cute baby sea otter", stream=True, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() assert cast(Any, response.is_closed) is True class TestAsyncImages: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create_variation(self, async_client: AsyncOpenAI) -> None: image = await async_client.images.create_variation( image=b"Example data", ) assert_matches_type(ImagesResponse, image, path=["response"]) @parametrize async def test_method_create_variation_with_all_params(self, async_client: AsyncOpenAI) -> None: image = await async_client.images.create_variation( image=b"Example data", model="string", n=1, response_format="url", size="1024x1024", user="user-1234", ) assert_matches_type(ImagesResponse, image, path=["response"]) @parametrize async def test_raw_response_create_variation(self, async_client: AsyncOpenAI) -> None: response = await async_client.images.with_raw_response.create_variation( image=b"Example data", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" image = response.parse() assert_matches_type(ImagesResponse, image, path=["response"]) @parametrize async def test_streaming_response_create_variation(self, async_client: AsyncOpenAI) -> None: async with async_client.images.with_streaming_response.create_variation( image=b"Example data", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" image = await response.parse() assert_matches_type(ImagesResponse, image, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_edit_overload_1(self, async_client: AsyncOpenAI) -> None: image = await async_client.images.edit( image=b"Example data", prompt="A cute baby sea otter wearing a beret", ) assert_matches_type(ImagesResponse, image, path=["response"]) @parametrize async def test_method_edit_with_all_params_overload_1(self, async_client: AsyncOpenAI) -> None: image = await async_client.images.edit( image=b"Example data", prompt="A cute baby sea otter wearing a beret", background="transparent", input_fidelity="high", mask=b"Example data", model="string", n=1, output_compression=100, output_format="png", partial_images=1, quality="high", response_format="url", size="1024x1024", stream=False, user="user-1234", ) assert_matches_type(ImagesResponse, image, path=["response"]) @parametrize async def test_raw_response_edit_overload_1(self, async_client: AsyncOpenAI) -> None: response = await async_client.images.with_raw_response.edit( image=b"Example data", prompt="A cute baby sea otter wearing a beret", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" image = response.parse() assert_matches_type(ImagesResponse, image, path=["response"]) @parametrize async def test_streaming_response_edit_overload_1(self, async_client: AsyncOpenAI) -> None: async with async_client.images.with_streaming_response.edit( image=b"Example data", prompt="A cute baby sea otter wearing a beret", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" image = await response.parse() assert_matches_type(ImagesResponse, image, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_edit_overload_2(self, async_client: AsyncOpenAI) -> None: image_stream = await async_client.images.edit( image=b"Example data", prompt="A cute baby sea otter wearing a beret", stream=True, ) await image_stream.response.aclose() @parametrize async def test_method_edit_with_all_params_overload_2(self, async_client: AsyncOpenAI) -> None: image_stream = await async_client.images.edit( image=b"Example data", prompt="A cute baby sea otter wearing a beret", stream=True, background="transparent", input_fidelity="high", mask=b"Example data", model="string", n=1, output_compression=100, output_format="png", partial_images=1, quality="high", response_format="url", size="1024x1024", user="user-1234", ) await image_stream.response.aclose() @parametrize async def test_raw_response_edit_overload_2(self, async_client: AsyncOpenAI) -> None: response = await async_client.images.with_raw_response.edit( image=b"Example data", prompt="A cute baby sea otter wearing a beret", stream=True, ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() await stream.close() @parametrize async def test_streaming_response_edit_overload_2(self, async_client: AsyncOpenAI) -> None: async with async_client.images.with_streaming_response.edit( image=b"Example data", prompt="A cute baby sea otter wearing a beret", stream=True, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = await response.parse() await stream.close() assert cast(Any, response.is_closed) is True @parametrize async def test_method_generate_overload_1(self, async_client: AsyncOpenAI) -> None: image = await async_client.images.generate( prompt="A cute baby sea otter", ) assert_matches_type(ImagesResponse, image, path=["response"]) @parametrize async def test_method_generate_with_all_params_overload_1(self, async_client: AsyncOpenAI) -> None: image = await async_client.images.generate( prompt="A cute baby sea otter", background="transparent", model="string", moderation="low", n=1, output_compression=100, output_format="png", partial_images=1, quality="medium", response_format="url", size="1024x1024", stream=False, style="vivid", user="user-1234", ) assert_matches_type(ImagesResponse, image, path=["response"]) @parametrize async def test_raw_response_generate_overload_1(self, async_client: AsyncOpenAI) -> None: response = await async_client.images.with_raw_response.generate( prompt="A cute baby sea otter", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" image = response.parse() assert_matches_type(ImagesResponse, image, path=["response"]) @parametrize async def test_streaming_response_generate_overload_1(self, async_client: AsyncOpenAI) -> None: async with async_client.images.with_streaming_response.generate( prompt="A cute baby sea otter", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" image = await response.parse() assert_matches_type(ImagesResponse, image, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_generate_overload_2(self, async_client: AsyncOpenAI) -> None: image_stream = await async_client.images.generate( prompt="A cute baby sea otter", stream=True, ) await image_stream.response.aclose() @parametrize async def test_method_generate_with_all_params_overload_2(self, async_client: AsyncOpenAI) -> None: image_stream = await async_client.images.generate( prompt="A cute baby sea otter", stream=True, background="transparent", model="string", moderation="low", n=1, output_compression=100, output_format="png", partial_images=1, quality="medium", response_format="url", size="1024x1024", style="vivid", user="user-1234", ) await image_stream.response.aclose() @parametrize async def test_raw_response_generate_overload_2(self, async_client: AsyncOpenAI) -> None: response = await async_client.images.with_raw_response.generate( prompt="A cute baby sea otter", stream=True, ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() await stream.close() @parametrize async def test_streaming_response_generate_overload_2(self, async_client: AsyncOpenAI) -> None: async with async_client.images.with_streaming_response.generate( prompt="A cute baby sea otter", stream=True, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = await response.parse() await stream.close() assert cast(Any, response.is_closed) is True ================================================ FILE: tests/api_resources/test_models.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types import Model, ModelDeleted from openai.pagination import SyncPage, AsyncPage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestModels: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_retrieve(self, client: OpenAI) -> None: model = client.models.retrieve( "gpt-4o-mini", ) assert_matches_type(Model, model, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: response = client.models.with_raw_response.retrieve( "gpt-4o-mini", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" model = response.parse() assert_matches_type(Model, model, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with client.models.with_streaming_response.retrieve( "gpt-4o-mini", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" model = response.parse() assert_matches_type(Model, model, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `model` but received ''"): client.models.with_raw_response.retrieve( "", ) @parametrize def test_method_list(self, client: OpenAI) -> None: model = client.models.list() assert_matches_type(SyncPage[Model], model, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.models.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" model = response.parse() assert_matches_type(SyncPage[Model], model, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.models.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" model = response.parse() assert_matches_type(SyncPage[Model], model, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_delete(self, client: OpenAI) -> None: model = client.models.delete( "ft:gpt-4o-mini:acemeco:suffix:abc123", ) assert_matches_type(ModelDeleted, model, path=["response"]) @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: response = client.models.with_raw_response.delete( "ft:gpt-4o-mini:acemeco:suffix:abc123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" model = response.parse() assert_matches_type(ModelDeleted, model, path=["response"]) @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with client.models.with_streaming_response.delete( "ft:gpt-4o-mini:acemeco:suffix:abc123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" model = response.parse() assert_matches_type(ModelDeleted, model, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `model` but received ''"): client.models.with_raw_response.delete( "", ) class TestAsyncModels: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: model = await async_client.models.retrieve( "gpt-4o-mini", ) assert_matches_type(Model, model, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: response = await async_client.models.with_raw_response.retrieve( "gpt-4o-mini", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" model = response.parse() assert_matches_type(Model, model, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: async with async_client.models.with_streaming_response.retrieve( "gpt-4o-mini", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" model = await response.parse() assert_matches_type(Model, model, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `model` but received ''"): await async_client.models.with_raw_response.retrieve( "", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: model = await async_client.models.list() assert_matches_type(AsyncPage[Model], model, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.models.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" model = response.parse() assert_matches_type(AsyncPage[Model], model, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.models.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" model = await response.parse() assert_matches_type(AsyncPage[Model], model, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: model = await async_client.models.delete( "ft:gpt-4o-mini:acemeco:suffix:abc123", ) assert_matches_type(ModelDeleted, model, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: response = await async_client.models.with_raw_response.delete( "ft:gpt-4o-mini:acemeco:suffix:abc123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" model = response.parse() assert_matches_type(ModelDeleted, model, path=["response"]) @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: async with async_client.models.with_streaming_response.delete( "ft:gpt-4o-mini:acemeco:suffix:abc123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" model = await response.parse() assert_matches_type(ModelDeleted, model, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `model` but received ''"): await async_client.models.with_raw_response.delete( "", ) ================================================ FILE: tests/api_resources/test_moderations.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types import ModerationCreateResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestModerations: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: moderation = client.moderations.create( input="I want to kill them.", ) assert_matches_type(ModerationCreateResponse, moderation, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: moderation = client.moderations.create( input="I want to kill them.", model="string", ) assert_matches_type(ModerationCreateResponse, moderation, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.moderations.with_raw_response.create( input="I want to kill them.", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" moderation = response.parse() assert_matches_type(ModerationCreateResponse, moderation, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.moderations.with_streaming_response.create( input="I want to kill them.", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" moderation = response.parse() assert_matches_type(ModerationCreateResponse, moderation, path=["response"]) assert cast(Any, response.is_closed) is True class TestAsyncModerations: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: moderation = await async_client.moderations.create( input="I want to kill them.", ) assert_matches_type(ModerationCreateResponse, moderation, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: moderation = await async_client.moderations.create( input="I want to kill them.", model="string", ) assert_matches_type(ModerationCreateResponse, moderation, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.moderations.with_raw_response.create( input="I want to kill them.", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" moderation = response.parse() assert_matches_type(ModerationCreateResponse, moderation, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.moderations.with_streaming_response.create( input="I want to kill them.", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" moderation = await response.parse() assert_matches_type(ModerationCreateResponse, moderation, path=["response"]) assert cast(Any, response.is_closed) is True ================================================ FILE: tests/api_resources/test_realtime.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os import pytest base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestRealtime: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) class TestAsyncRealtime: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) ================================================ FILE: tests/api_resources/test_responses.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai._utils import assert_signatures_in_sync from openai.types.responses import ( Response, CompactedResponse, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestResponses: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create_overload_1(self, client: OpenAI) -> None: response = client.responses.create() assert_matches_type(Response, response, path=["response"]) @parametrize def test_method_create_with_all_params_overload_1(self, client: OpenAI) -> None: response = client.responses.create( background=True, context_management=[ { "type": "type", "compact_threshold": 1000, } ], conversation="string", include=["file_search_call.results"], input="string", instructions="instructions", max_output_tokens=0, max_tool_calls=0, metadata={"foo": "string"}, model="gpt-5.1", parallel_tool_calls=True, previous_response_id="previous_response_id", prompt={ "id": "id", "variables": {"foo": "string"}, "version": "version", }, prompt_cache_key="prompt-cache-key-1234", prompt_cache_retention="in-memory", reasoning={ "effort": "none", "generate_summary": "auto", "summary": "auto", }, safety_identifier="safety-identifier-1234", service_tier="auto", store=True, stream=False, stream_options={"include_obfuscation": True}, temperature=1, text={ "format": {"type": "text"}, "verbosity": "low", }, tool_choice="none", tools=[ { "name": "name", "parameters": {"foo": "bar"}, "strict": True, "type": "function", "defer_loading": True, "description": "description", } ], top_logprobs=0, top_p=1, truncation="auto", user="user-1234", ) assert_matches_type(Response, response, path=["response"]) @parametrize def test_raw_response_create_overload_1(self, client: OpenAI) -> None: http_response = client.responses.with_raw_response.create() assert http_response.is_closed is True assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = http_response.parse() assert_matches_type(Response, response, path=["response"]) @parametrize def test_streaming_response_create_overload_1(self, client: OpenAI) -> None: with client.responses.with_streaming_response.create() as http_response: assert not http_response.is_closed assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = http_response.parse() assert_matches_type(Response, response, path=["response"]) assert cast(Any, http_response.is_closed) is True @parametrize def test_method_create_overload_2(self, client: OpenAI) -> None: response_stream = client.responses.create( stream=True, ) response_stream.response.close() @parametrize def test_method_create_with_all_params_overload_2(self, client: OpenAI) -> None: response_stream = client.responses.create( stream=True, background=True, context_management=[ { "type": "type", "compact_threshold": 1000, } ], conversation="string", include=["file_search_call.results"], input="string", instructions="instructions", max_output_tokens=0, max_tool_calls=0, metadata={"foo": "string"}, model="gpt-5.1", parallel_tool_calls=True, previous_response_id="previous_response_id", prompt={ "id": "id", "variables": {"foo": "string"}, "version": "version", }, prompt_cache_key="prompt-cache-key-1234", prompt_cache_retention="in-memory", reasoning={ "effort": "none", "generate_summary": "auto", "summary": "auto", }, safety_identifier="safety-identifier-1234", service_tier="auto", store=True, stream_options={"include_obfuscation": True}, temperature=1, text={ "format": {"type": "text"}, "verbosity": "low", }, tool_choice="none", tools=[ { "name": "name", "parameters": {"foo": "bar"}, "strict": True, "type": "function", "defer_loading": True, "description": "description", } ], top_logprobs=0, top_p=1, truncation="auto", user="user-1234", ) response_stream.response.close() @parametrize def test_raw_response_create_overload_2(self, client: OpenAI) -> None: response = client.responses.with_raw_response.create( stream=True, ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() @parametrize def test_streaming_response_create_overload_2(self, client: OpenAI) -> None: with client.responses.with_streaming_response.create( stream=True, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() assert cast(Any, response.is_closed) is True @parametrize def test_method_retrieve_overload_1(self, client: OpenAI) -> None: response = client.responses.retrieve( response_id="resp_677efb5139a88190b512bc3fef8e535d", ) assert_matches_type(Response, response, path=["response"]) @parametrize def test_method_retrieve_with_all_params_overload_1(self, client: OpenAI) -> None: response = client.responses.retrieve( response_id="resp_677efb5139a88190b512bc3fef8e535d", include=["file_search_call.results"], include_obfuscation=True, starting_after=0, stream=False, ) assert_matches_type(Response, response, path=["response"]) @parametrize def test_raw_response_retrieve_overload_1(self, client: OpenAI) -> None: http_response = client.responses.with_raw_response.retrieve( response_id="resp_677efb5139a88190b512bc3fef8e535d", ) assert http_response.is_closed is True assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = http_response.parse() assert_matches_type(Response, response, path=["response"]) @parametrize def test_streaming_response_retrieve_overload_1(self, client: OpenAI) -> None: with client.responses.with_streaming_response.retrieve( response_id="resp_677efb5139a88190b512bc3fef8e535d", ) as http_response: assert not http_response.is_closed assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = http_response.parse() assert_matches_type(Response, response, path=["response"]) assert cast(Any, http_response.is_closed) is True @parametrize def test_path_params_retrieve_overload_1(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `response_id` but received ''"): client.responses.with_raw_response.retrieve( response_id="", ) @parametrize def test_method_retrieve_overload_2(self, client: OpenAI) -> None: response_stream = client.responses.retrieve( response_id="resp_677efb5139a88190b512bc3fef8e535d", stream=True, ) response_stream.response.close() @parametrize def test_method_retrieve_with_all_params_overload_2(self, client: OpenAI) -> None: response_stream = client.responses.retrieve( response_id="resp_677efb5139a88190b512bc3fef8e535d", stream=True, include=["file_search_call.results"], include_obfuscation=True, starting_after=0, ) response_stream.response.close() @parametrize def test_raw_response_retrieve_overload_2(self, client: OpenAI) -> None: response = client.responses.with_raw_response.retrieve( response_id="resp_677efb5139a88190b512bc3fef8e535d", stream=True, ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() @parametrize def test_streaming_response_retrieve_overload_2(self, client: OpenAI) -> None: with client.responses.with_streaming_response.retrieve( response_id="resp_677efb5139a88190b512bc3fef8e535d", stream=True, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() stream.close() assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve_overload_2(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `response_id` but received ''"): client.responses.with_raw_response.retrieve( response_id="", stream=True, ) @parametrize def test_method_delete(self, client: OpenAI) -> None: response = client.responses.delete( "resp_677efb5139a88190b512bc3fef8e535d", ) assert response is None @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: http_response = client.responses.with_raw_response.delete( "resp_677efb5139a88190b512bc3fef8e535d", ) assert http_response.is_closed is True assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = http_response.parse() assert response is None @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with client.responses.with_streaming_response.delete( "resp_677efb5139a88190b512bc3fef8e535d", ) as http_response: assert not http_response.is_closed assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = http_response.parse() assert response is None assert cast(Any, http_response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `response_id` but received ''"): client.responses.with_raw_response.delete( "", ) @parametrize def test_method_cancel(self, client: OpenAI) -> None: response = client.responses.cancel( "resp_677efb5139a88190b512bc3fef8e535d", ) assert_matches_type(Response, response, path=["response"]) @parametrize def test_raw_response_cancel(self, client: OpenAI) -> None: http_response = client.responses.with_raw_response.cancel( "resp_677efb5139a88190b512bc3fef8e535d", ) assert http_response.is_closed is True assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = http_response.parse() assert_matches_type(Response, response, path=["response"]) @parametrize def test_streaming_response_cancel(self, client: OpenAI) -> None: with client.responses.with_streaming_response.cancel( "resp_677efb5139a88190b512bc3fef8e535d", ) as http_response: assert not http_response.is_closed assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = http_response.parse() assert_matches_type(Response, response, path=["response"]) assert cast(Any, http_response.is_closed) is True @parametrize def test_path_params_cancel(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `response_id` but received ''"): client.responses.with_raw_response.cancel( "", ) @parametrize def test_method_compact(self, client: OpenAI) -> None: response = client.responses.compact( model="gpt-5.4", ) assert_matches_type(CompactedResponse, response, path=["response"]) @parametrize def test_method_compact_with_all_params(self, client: OpenAI) -> None: response = client.responses.compact( model="gpt-5.4", input="string", instructions="instructions", previous_response_id="resp_123", prompt_cache_key="prompt_cache_key", ) assert_matches_type(CompactedResponse, response, path=["response"]) @parametrize def test_raw_response_compact(self, client: OpenAI) -> None: http_response = client.responses.with_raw_response.compact( model="gpt-5.4", ) assert http_response.is_closed is True assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = http_response.parse() assert_matches_type(CompactedResponse, response, path=["response"]) @parametrize def test_streaming_response_compact(self, client: OpenAI) -> None: with client.responses.with_streaming_response.compact( model="gpt-5.4", ) as http_response: assert not http_response.is_closed assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = http_response.parse() assert_matches_type(CompactedResponse, response, path=["response"]) assert cast(Any, http_response.is_closed) is True @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) def test_parse_method_in_sync(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: checking_client: OpenAI | AsyncOpenAI = client if sync else async_client assert_signatures_in_sync( checking_client.responses.create, checking_client.responses.parse, exclude_params={"stream", "tools"}, ) class TestAsyncResponses: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create_overload_1(self, async_client: AsyncOpenAI) -> None: response = await async_client.responses.create() assert_matches_type(Response, response, path=["response"]) @parametrize async def test_method_create_with_all_params_overload_1(self, async_client: AsyncOpenAI) -> None: response = await async_client.responses.create( background=True, context_management=[ { "type": "type", "compact_threshold": 1000, } ], conversation="string", include=["file_search_call.results"], input="string", instructions="instructions", max_output_tokens=0, max_tool_calls=0, metadata={"foo": "string"}, model="gpt-5.1", parallel_tool_calls=True, previous_response_id="previous_response_id", prompt={ "id": "id", "variables": {"foo": "string"}, "version": "version", }, prompt_cache_key="prompt-cache-key-1234", prompt_cache_retention="in-memory", reasoning={ "effort": "none", "generate_summary": "auto", "summary": "auto", }, safety_identifier="safety-identifier-1234", service_tier="auto", store=True, stream=False, stream_options={"include_obfuscation": True}, temperature=1, text={ "format": {"type": "text"}, "verbosity": "low", }, tool_choice="none", tools=[ { "name": "name", "parameters": {"foo": "bar"}, "strict": True, "type": "function", "defer_loading": True, "description": "description", } ], top_logprobs=0, top_p=1, truncation="auto", user="user-1234", ) assert_matches_type(Response, response, path=["response"]) @parametrize async def test_raw_response_create_overload_1(self, async_client: AsyncOpenAI) -> None: http_response = await async_client.responses.with_raw_response.create() assert http_response.is_closed is True assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = http_response.parse() assert_matches_type(Response, response, path=["response"]) @parametrize async def test_streaming_response_create_overload_1(self, async_client: AsyncOpenAI) -> None: async with async_client.responses.with_streaming_response.create() as http_response: assert not http_response.is_closed assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = await http_response.parse() assert_matches_type(Response, response, path=["response"]) assert cast(Any, http_response.is_closed) is True @parametrize async def test_method_create_overload_2(self, async_client: AsyncOpenAI) -> None: response_stream = await async_client.responses.create( stream=True, ) await response_stream.response.aclose() @parametrize async def test_method_create_with_all_params_overload_2(self, async_client: AsyncOpenAI) -> None: response_stream = await async_client.responses.create( stream=True, background=True, context_management=[ { "type": "type", "compact_threshold": 1000, } ], conversation="string", include=["file_search_call.results"], input="string", instructions="instructions", max_output_tokens=0, max_tool_calls=0, metadata={"foo": "string"}, model="gpt-5.1", parallel_tool_calls=True, previous_response_id="previous_response_id", prompt={ "id": "id", "variables": {"foo": "string"}, "version": "version", }, prompt_cache_key="prompt-cache-key-1234", prompt_cache_retention="in-memory", reasoning={ "effort": "none", "generate_summary": "auto", "summary": "auto", }, safety_identifier="safety-identifier-1234", service_tier="auto", store=True, stream_options={"include_obfuscation": True}, temperature=1, text={ "format": {"type": "text"}, "verbosity": "low", }, tool_choice="none", tools=[ { "name": "name", "parameters": {"foo": "bar"}, "strict": True, "type": "function", "defer_loading": True, "description": "description", } ], top_logprobs=0, top_p=1, truncation="auto", user="user-1234", ) await response_stream.response.aclose() @parametrize async def test_raw_response_create_overload_2(self, async_client: AsyncOpenAI) -> None: response = await async_client.responses.with_raw_response.create( stream=True, ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() await stream.close() @parametrize async def test_streaming_response_create_overload_2(self, async_client: AsyncOpenAI) -> None: async with async_client.responses.with_streaming_response.create( stream=True, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = await response.parse() await stream.close() assert cast(Any, response.is_closed) is True @parametrize async def test_method_retrieve_overload_1(self, async_client: AsyncOpenAI) -> None: response = await async_client.responses.retrieve( response_id="resp_677efb5139a88190b512bc3fef8e535d", ) assert_matches_type(Response, response, path=["response"]) @parametrize async def test_method_retrieve_with_all_params_overload_1(self, async_client: AsyncOpenAI) -> None: response = await async_client.responses.retrieve( response_id="resp_677efb5139a88190b512bc3fef8e535d", include=["file_search_call.results"], include_obfuscation=True, starting_after=0, stream=False, ) assert_matches_type(Response, response, path=["response"]) @parametrize async def test_raw_response_retrieve_overload_1(self, async_client: AsyncOpenAI) -> None: http_response = await async_client.responses.with_raw_response.retrieve( response_id="resp_677efb5139a88190b512bc3fef8e535d", ) assert http_response.is_closed is True assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = http_response.parse() assert_matches_type(Response, response, path=["response"]) @parametrize async def test_streaming_response_retrieve_overload_1(self, async_client: AsyncOpenAI) -> None: async with async_client.responses.with_streaming_response.retrieve( response_id="resp_677efb5139a88190b512bc3fef8e535d", ) as http_response: assert not http_response.is_closed assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = await http_response.parse() assert_matches_type(Response, response, path=["response"]) assert cast(Any, http_response.is_closed) is True @parametrize async def test_path_params_retrieve_overload_1(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `response_id` but received ''"): await async_client.responses.with_raw_response.retrieve( response_id="", ) @parametrize async def test_method_retrieve_overload_2(self, async_client: AsyncOpenAI) -> None: response_stream = await async_client.responses.retrieve( response_id="resp_677efb5139a88190b512bc3fef8e535d", stream=True, ) await response_stream.response.aclose() @parametrize async def test_method_retrieve_with_all_params_overload_2(self, async_client: AsyncOpenAI) -> None: response_stream = await async_client.responses.retrieve( response_id="resp_677efb5139a88190b512bc3fef8e535d", stream=True, include=["file_search_call.results"], include_obfuscation=True, starting_after=0, ) await response_stream.response.aclose() @parametrize async def test_raw_response_retrieve_overload_2(self, async_client: AsyncOpenAI) -> None: response = await async_client.responses.with_raw_response.retrieve( response_id="resp_677efb5139a88190b512bc3fef8e535d", stream=True, ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = response.parse() await stream.close() @parametrize async def test_streaming_response_retrieve_overload_2(self, async_client: AsyncOpenAI) -> None: async with async_client.responses.with_streaming_response.retrieve( response_id="resp_677efb5139a88190b512bc3fef8e535d", stream=True, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" stream = await response.parse() await stream.close() assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve_overload_2(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `response_id` but received ''"): await async_client.responses.with_raw_response.retrieve( response_id="", stream=True, ) @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: response = await async_client.responses.delete( "resp_677efb5139a88190b512bc3fef8e535d", ) assert response is None @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: http_response = await async_client.responses.with_raw_response.delete( "resp_677efb5139a88190b512bc3fef8e535d", ) assert http_response.is_closed is True assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = http_response.parse() assert response is None @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: async with async_client.responses.with_streaming_response.delete( "resp_677efb5139a88190b512bc3fef8e535d", ) as http_response: assert not http_response.is_closed assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = await http_response.parse() assert response is None assert cast(Any, http_response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `response_id` but received ''"): await async_client.responses.with_raw_response.delete( "", ) @parametrize async def test_method_cancel(self, async_client: AsyncOpenAI) -> None: response = await async_client.responses.cancel( "resp_677efb5139a88190b512bc3fef8e535d", ) assert_matches_type(Response, response, path=["response"]) @parametrize async def test_raw_response_cancel(self, async_client: AsyncOpenAI) -> None: http_response = await async_client.responses.with_raw_response.cancel( "resp_677efb5139a88190b512bc3fef8e535d", ) assert http_response.is_closed is True assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = http_response.parse() assert_matches_type(Response, response, path=["response"]) @parametrize async def test_streaming_response_cancel(self, async_client: AsyncOpenAI) -> None: async with async_client.responses.with_streaming_response.cancel( "resp_677efb5139a88190b512bc3fef8e535d", ) as http_response: assert not http_response.is_closed assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = await http_response.parse() assert_matches_type(Response, response, path=["response"]) assert cast(Any, http_response.is_closed) is True @parametrize async def test_path_params_cancel(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `response_id` but received ''"): await async_client.responses.with_raw_response.cancel( "", ) @parametrize async def test_method_compact(self, async_client: AsyncOpenAI) -> None: response = await async_client.responses.compact( model="gpt-5.4", ) assert_matches_type(CompactedResponse, response, path=["response"]) @parametrize async def test_method_compact_with_all_params(self, async_client: AsyncOpenAI) -> None: response = await async_client.responses.compact( model="gpt-5.4", input="string", instructions="instructions", previous_response_id="resp_123", prompt_cache_key="prompt_cache_key", ) assert_matches_type(CompactedResponse, response, path=["response"]) @parametrize async def test_raw_response_compact(self, async_client: AsyncOpenAI) -> None: http_response = await async_client.responses.with_raw_response.compact( model="gpt-5.4", ) assert http_response.is_closed is True assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = http_response.parse() assert_matches_type(CompactedResponse, response, path=["response"]) @parametrize async def test_streaming_response_compact(self, async_client: AsyncOpenAI) -> None: async with async_client.responses.with_streaming_response.compact( model="gpt-5.4", ) as http_response: assert not http_response.is_closed assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" response = await http_response.parse() assert_matches_type(CompactedResponse, response, path=["response"]) assert cast(Any, http_response.is_closed) is True ================================================ FILE: tests/api_resources/test_skills.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types import Skill, DeletedSkill from openai.pagination import SyncCursorPage, AsyncCursorPage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestSkills: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: skill = client.skills.create() assert_matches_type(Skill, skill, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: skill = client.skills.create( files=[b"Example data"], ) assert_matches_type(Skill, skill, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.skills.with_raw_response.create() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = response.parse() assert_matches_type(Skill, skill, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.skills.with_streaming_response.create() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = response.parse() assert_matches_type(Skill, skill, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_retrieve(self, client: OpenAI) -> None: skill = client.skills.retrieve( "skill_123", ) assert_matches_type(Skill, skill, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: response = client.skills.with_raw_response.retrieve( "skill_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = response.parse() assert_matches_type(Skill, skill, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with client.skills.with_streaming_response.retrieve( "skill_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = response.parse() assert_matches_type(Skill, skill, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `skill_id` but received ''"): client.skills.with_raw_response.retrieve( "", ) @parametrize def test_method_update(self, client: OpenAI) -> None: skill = client.skills.update( skill_id="skill_123", default_version="default_version", ) assert_matches_type(Skill, skill, path=["response"]) @parametrize def test_raw_response_update(self, client: OpenAI) -> None: response = client.skills.with_raw_response.update( skill_id="skill_123", default_version="default_version", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = response.parse() assert_matches_type(Skill, skill, path=["response"]) @parametrize def test_streaming_response_update(self, client: OpenAI) -> None: with client.skills.with_streaming_response.update( skill_id="skill_123", default_version="default_version", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = response.parse() assert_matches_type(Skill, skill, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_update(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `skill_id` but received ''"): client.skills.with_raw_response.update( skill_id="", default_version="default_version", ) @parametrize def test_method_list(self, client: OpenAI) -> None: skill = client.skills.list() assert_matches_type(SyncCursorPage[Skill], skill, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: skill = client.skills.list( after="after", limit=0, order="asc", ) assert_matches_type(SyncCursorPage[Skill], skill, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.skills.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = response.parse() assert_matches_type(SyncCursorPage[Skill], skill, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.skills.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = response.parse() assert_matches_type(SyncCursorPage[Skill], skill, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_delete(self, client: OpenAI) -> None: skill = client.skills.delete( "skill_123", ) assert_matches_type(DeletedSkill, skill, path=["response"]) @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: response = client.skills.with_raw_response.delete( "skill_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = response.parse() assert_matches_type(DeletedSkill, skill, path=["response"]) @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with client.skills.with_streaming_response.delete( "skill_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = response.parse() assert_matches_type(DeletedSkill, skill, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `skill_id` but received ''"): client.skills.with_raw_response.delete( "", ) class TestAsyncSkills: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: skill = await async_client.skills.create() assert_matches_type(Skill, skill, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: skill = await async_client.skills.create( files=[b"Example data"], ) assert_matches_type(Skill, skill, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.skills.with_raw_response.create() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = response.parse() assert_matches_type(Skill, skill, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.skills.with_streaming_response.create() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = await response.parse() assert_matches_type(Skill, skill, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: skill = await async_client.skills.retrieve( "skill_123", ) assert_matches_type(Skill, skill, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: response = await async_client.skills.with_raw_response.retrieve( "skill_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = response.parse() assert_matches_type(Skill, skill, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: async with async_client.skills.with_streaming_response.retrieve( "skill_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = await response.parse() assert_matches_type(Skill, skill, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `skill_id` but received ''"): await async_client.skills.with_raw_response.retrieve( "", ) @parametrize async def test_method_update(self, async_client: AsyncOpenAI) -> None: skill = await async_client.skills.update( skill_id="skill_123", default_version="default_version", ) assert_matches_type(Skill, skill, path=["response"]) @parametrize async def test_raw_response_update(self, async_client: AsyncOpenAI) -> None: response = await async_client.skills.with_raw_response.update( skill_id="skill_123", default_version="default_version", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = response.parse() assert_matches_type(Skill, skill, path=["response"]) @parametrize async def test_streaming_response_update(self, async_client: AsyncOpenAI) -> None: async with async_client.skills.with_streaming_response.update( skill_id="skill_123", default_version="default_version", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = await response.parse() assert_matches_type(Skill, skill, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_update(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `skill_id` but received ''"): await async_client.skills.with_raw_response.update( skill_id="", default_version="default_version", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: skill = await async_client.skills.list() assert_matches_type(AsyncCursorPage[Skill], skill, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: skill = await async_client.skills.list( after="after", limit=0, order="asc", ) assert_matches_type(AsyncCursorPage[Skill], skill, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.skills.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = response.parse() assert_matches_type(AsyncCursorPage[Skill], skill, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.skills.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = await response.parse() assert_matches_type(AsyncCursorPage[Skill], skill, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: skill = await async_client.skills.delete( "skill_123", ) assert_matches_type(DeletedSkill, skill, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: response = await async_client.skills.with_raw_response.delete( "skill_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = response.parse() assert_matches_type(DeletedSkill, skill, path=["response"]) @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: async with async_client.skills.with_streaming_response.delete( "skill_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" skill = await response.parse() assert_matches_type(DeletedSkill, skill, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `skill_id` but received ''"): await async_client.skills.with_raw_response.delete( "", ) ================================================ FILE: tests/api_resources/test_uploads.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types import Upload base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestUploads: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: upload = client.uploads.create( bytes=0, filename="filename", mime_type="mime_type", purpose="assistants", ) assert_matches_type(Upload, upload, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: upload = client.uploads.create( bytes=0, filename="filename", mime_type="mime_type", purpose="assistants", expires_after={ "anchor": "created_at", "seconds": 3600, }, ) assert_matches_type(Upload, upload, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.uploads.with_raw_response.create( bytes=0, filename="filename", mime_type="mime_type", purpose="assistants", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" upload = response.parse() assert_matches_type(Upload, upload, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.uploads.with_streaming_response.create( bytes=0, filename="filename", mime_type="mime_type", purpose="assistants", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" upload = response.parse() assert_matches_type(Upload, upload, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_cancel(self, client: OpenAI) -> None: upload = client.uploads.cancel( "upload_abc123", ) assert_matches_type(Upload, upload, path=["response"]) @parametrize def test_raw_response_cancel(self, client: OpenAI) -> None: response = client.uploads.with_raw_response.cancel( "upload_abc123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" upload = response.parse() assert_matches_type(Upload, upload, path=["response"]) @parametrize def test_streaming_response_cancel(self, client: OpenAI) -> None: with client.uploads.with_streaming_response.cancel( "upload_abc123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" upload = response.parse() assert_matches_type(Upload, upload, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_cancel(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `upload_id` but received ''"): client.uploads.with_raw_response.cancel( "", ) @parametrize def test_method_complete(self, client: OpenAI) -> None: upload = client.uploads.complete( upload_id="upload_abc123", part_ids=["string"], ) assert_matches_type(Upload, upload, path=["response"]) @parametrize def test_method_complete_with_all_params(self, client: OpenAI) -> None: upload = client.uploads.complete( upload_id="upload_abc123", part_ids=["string"], md5="md5", ) assert_matches_type(Upload, upload, path=["response"]) @parametrize def test_raw_response_complete(self, client: OpenAI) -> None: response = client.uploads.with_raw_response.complete( upload_id="upload_abc123", part_ids=["string"], ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" upload = response.parse() assert_matches_type(Upload, upload, path=["response"]) @parametrize def test_streaming_response_complete(self, client: OpenAI) -> None: with client.uploads.with_streaming_response.complete( upload_id="upload_abc123", part_ids=["string"], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" upload = response.parse() assert_matches_type(Upload, upload, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_complete(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `upload_id` but received ''"): client.uploads.with_raw_response.complete( upload_id="", part_ids=["string"], ) class TestAsyncUploads: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: upload = await async_client.uploads.create( bytes=0, filename="filename", mime_type="mime_type", purpose="assistants", ) assert_matches_type(Upload, upload, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: upload = await async_client.uploads.create( bytes=0, filename="filename", mime_type="mime_type", purpose="assistants", expires_after={ "anchor": "created_at", "seconds": 3600, }, ) assert_matches_type(Upload, upload, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.uploads.with_raw_response.create( bytes=0, filename="filename", mime_type="mime_type", purpose="assistants", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" upload = response.parse() assert_matches_type(Upload, upload, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.uploads.with_streaming_response.create( bytes=0, filename="filename", mime_type="mime_type", purpose="assistants", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" upload = await response.parse() assert_matches_type(Upload, upload, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_cancel(self, async_client: AsyncOpenAI) -> None: upload = await async_client.uploads.cancel( "upload_abc123", ) assert_matches_type(Upload, upload, path=["response"]) @parametrize async def test_raw_response_cancel(self, async_client: AsyncOpenAI) -> None: response = await async_client.uploads.with_raw_response.cancel( "upload_abc123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" upload = response.parse() assert_matches_type(Upload, upload, path=["response"]) @parametrize async def test_streaming_response_cancel(self, async_client: AsyncOpenAI) -> None: async with async_client.uploads.with_streaming_response.cancel( "upload_abc123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" upload = await response.parse() assert_matches_type(Upload, upload, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_cancel(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `upload_id` but received ''"): await async_client.uploads.with_raw_response.cancel( "", ) @parametrize async def test_method_complete(self, async_client: AsyncOpenAI) -> None: upload = await async_client.uploads.complete( upload_id="upload_abc123", part_ids=["string"], ) assert_matches_type(Upload, upload, path=["response"]) @parametrize async def test_method_complete_with_all_params(self, async_client: AsyncOpenAI) -> None: upload = await async_client.uploads.complete( upload_id="upload_abc123", part_ids=["string"], md5="md5", ) assert_matches_type(Upload, upload, path=["response"]) @parametrize async def test_raw_response_complete(self, async_client: AsyncOpenAI) -> None: response = await async_client.uploads.with_raw_response.complete( upload_id="upload_abc123", part_ids=["string"], ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" upload = response.parse() assert_matches_type(Upload, upload, path=["response"]) @parametrize async def test_streaming_response_complete(self, async_client: AsyncOpenAI) -> None: async with async_client.uploads.with_streaming_response.complete( upload_id="upload_abc123", part_ids=["string"], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" upload = await response.parse() assert_matches_type(Upload, upload, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_complete(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `upload_id` but received ''"): await async_client.uploads.with_raw_response.complete( upload_id="", part_ids=["string"], ) ================================================ FILE: tests/api_resources/test_vector_stores.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types import ( VectorStore, VectorStoreDeleted, VectorStoreSearchResponse, ) from openai.pagination import SyncPage, AsyncPage, SyncCursorPage, AsyncCursorPage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestVectorStores: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: vector_store = client.vector_stores.create() assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: vector_store = client.vector_stores.create( chunking_strategy={"type": "auto"}, description="description", expires_after={ "anchor": "last_active_at", "days": 1, }, file_ids=["string"], metadata={"foo": "string"}, name="name", ) assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.vector_stores.with_raw_response.create() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = response.parse() assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.vector_stores.with_streaming_response.create() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = response.parse() assert_matches_type(VectorStore, vector_store, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_retrieve(self, client: OpenAI) -> None: vector_store = client.vector_stores.retrieve( "vector_store_id", ) assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: response = client.vector_stores.with_raw_response.retrieve( "vector_store_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = response.parse() assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with client.vector_stores.with_streaming_response.retrieve( "vector_store_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = response.parse() assert_matches_type(VectorStore, vector_store, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): client.vector_stores.with_raw_response.retrieve( "", ) @parametrize def test_method_update(self, client: OpenAI) -> None: vector_store = client.vector_stores.update( vector_store_id="vector_store_id", ) assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize def test_method_update_with_all_params(self, client: OpenAI) -> None: vector_store = client.vector_stores.update( vector_store_id="vector_store_id", expires_after={ "anchor": "last_active_at", "days": 1, }, metadata={"foo": "string"}, name="name", ) assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize def test_raw_response_update(self, client: OpenAI) -> None: response = client.vector_stores.with_raw_response.update( vector_store_id="vector_store_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = response.parse() assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize def test_streaming_response_update(self, client: OpenAI) -> None: with client.vector_stores.with_streaming_response.update( vector_store_id="vector_store_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = response.parse() assert_matches_type(VectorStore, vector_store, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_update(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): client.vector_stores.with_raw_response.update( vector_store_id="", ) @parametrize def test_method_list(self, client: OpenAI) -> None: vector_store = client.vector_stores.list() assert_matches_type(SyncCursorPage[VectorStore], vector_store, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: vector_store = client.vector_stores.list( after="after", before="before", limit=0, order="asc", ) assert_matches_type(SyncCursorPage[VectorStore], vector_store, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.vector_stores.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = response.parse() assert_matches_type(SyncCursorPage[VectorStore], vector_store, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.vector_stores.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = response.parse() assert_matches_type(SyncCursorPage[VectorStore], vector_store, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_delete(self, client: OpenAI) -> None: vector_store = client.vector_stores.delete( "vector_store_id", ) assert_matches_type(VectorStoreDeleted, vector_store, path=["response"]) @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: response = client.vector_stores.with_raw_response.delete( "vector_store_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = response.parse() assert_matches_type(VectorStoreDeleted, vector_store, path=["response"]) @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with client.vector_stores.with_streaming_response.delete( "vector_store_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = response.parse() assert_matches_type(VectorStoreDeleted, vector_store, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): client.vector_stores.with_raw_response.delete( "", ) @parametrize def test_method_search(self, client: OpenAI) -> None: vector_store = client.vector_stores.search( vector_store_id="vs_abc123", query="string", ) assert_matches_type(SyncPage[VectorStoreSearchResponse], vector_store, path=["response"]) @parametrize def test_method_search_with_all_params(self, client: OpenAI) -> None: vector_store = client.vector_stores.search( vector_store_id="vs_abc123", query="string", filters={ "key": "key", "type": "eq", "value": "string", }, max_num_results=1, ranking_options={ "ranker": "none", "score_threshold": 0, }, rewrite_query=True, ) assert_matches_type(SyncPage[VectorStoreSearchResponse], vector_store, path=["response"]) @parametrize def test_raw_response_search(self, client: OpenAI) -> None: response = client.vector_stores.with_raw_response.search( vector_store_id="vs_abc123", query="string", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = response.parse() assert_matches_type(SyncPage[VectorStoreSearchResponse], vector_store, path=["response"]) @parametrize def test_streaming_response_search(self, client: OpenAI) -> None: with client.vector_stores.with_streaming_response.search( vector_store_id="vs_abc123", query="string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = response.parse() assert_matches_type(SyncPage[VectorStoreSearchResponse], vector_store, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_search(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): client.vector_stores.with_raw_response.search( vector_store_id="", query="string", ) class TestAsyncVectorStores: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: vector_store = await async_client.vector_stores.create() assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: vector_store = await async_client.vector_stores.create( chunking_strategy={"type": "auto"}, description="description", expires_after={ "anchor": "last_active_at", "days": 1, }, file_ids=["string"], metadata={"foo": "string"}, name="name", ) assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.vector_stores.with_raw_response.create() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = response.parse() assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.vector_stores.with_streaming_response.create() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = await response.parse() assert_matches_type(VectorStore, vector_store, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: vector_store = await async_client.vector_stores.retrieve( "vector_store_id", ) assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: response = await async_client.vector_stores.with_raw_response.retrieve( "vector_store_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = response.parse() assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: async with async_client.vector_stores.with_streaming_response.retrieve( "vector_store_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = await response.parse() assert_matches_type(VectorStore, vector_store, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): await async_client.vector_stores.with_raw_response.retrieve( "", ) @parametrize async def test_method_update(self, async_client: AsyncOpenAI) -> None: vector_store = await async_client.vector_stores.update( vector_store_id="vector_store_id", ) assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize async def test_method_update_with_all_params(self, async_client: AsyncOpenAI) -> None: vector_store = await async_client.vector_stores.update( vector_store_id="vector_store_id", expires_after={ "anchor": "last_active_at", "days": 1, }, metadata={"foo": "string"}, name="name", ) assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize async def test_raw_response_update(self, async_client: AsyncOpenAI) -> None: response = await async_client.vector_stores.with_raw_response.update( vector_store_id="vector_store_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = response.parse() assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize async def test_streaming_response_update(self, async_client: AsyncOpenAI) -> None: async with async_client.vector_stores.with_streaming_response.update( vector_store_id="vector_store_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = await response.parse() assert_matches_type(VectorStore, vector_store, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_update(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): await async_client.vector_stores.with_raw_response.update( vector_store_id="", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: vector_store = await async_client.vector_stores.list() assert_matches_type(AsyncCursorPage[VectorStore], vector_store, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: vector_store = await async_client.vector_stores.list( after="after", before="before", limit=0, order="asc", ) assert_matches_type(AsyncCursorPage[VectorStore], vector_store, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.vector_stores.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = response.parse() assert_matches_type(AsyncCursorPage[VectorStore], vector_store, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.vector_stores.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = await response.parse() assert_matches_type(AsyncCursorPage[VectorStore], vector_store, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: vector_store = await async_client.vector_stores.delete( "vector_store_id", ) assert_matches_type(VectorStoreDeleted, vector_store, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: response = await async_client.vector_stores.with_raw_response.delete( "vector_store_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = response.parse() assert_matches_type(VectorStoreDeleted, vector_store, path=["response"]) @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: async with async_client.vector_stores.with_streaming_response.delete( "vector_store_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = await response.parse() assert_matches_type(VectorStoreDeleted, vector_store, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): await async_client.vector_stores.with_raw_response.delete( "", ) @parametrize async def test_method_search(self, async_client: AsyncOpenAI) -> None: vector_store = await async_client.vector_stores.search( vector_store_id="vs_abc123", query="string", ) assert_matches_type(AsyncPage[VectorStoreSearchResponse], vector_store, path=["response"]) @parametrize async def test_method_search_with_all_params(self, async_client: AsyncOpenAI) -> None: vector_store = await async_client.vector_stores.search( vector_store_id="vs_abc123", query="string", filters={ "key": "key", "type": "eq", "value": "string", }, max_num_results=1, ranking_options={ "ranker": "none", "score_threshold": 0, }, rewrite_query=True, ) assert_matches_type(AsyncPage[VectorStoreSearchResponse], vector_store, path=["response"]) @parametrize async def test_raw_response_search(self, async_client: AsyncOpenAI) -> None: response = await async_client.vector_stores.with_raw_response.search( vector_store_id="vs_abc123", query="string", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = response.parse() assert_matches_type(AsyncPage[VectorStoreSearchResponse], vector_store, path=["response"]) @parametrize async def test_streaming_response_search(self, async_client: AsyncOpenAI) -> None: async with async_client.vector_stores.with_streaming_response.search( vector_store_id="vs_abc123", query="string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" vector_store = await response.parse() assert_matches_type(AsyncPage[VectorStoreSearchResponse], vector_store, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_search(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): await async_client.vector_stores.with_raw_response.search( vector_store_id="", query="string", ) ================================================ FILE: tests/api_resources/test_videos.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import httpx import pytest from respx import MockRouter import openai._legacy_response as _legacy_response from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types import ( Video, VideoDeleteResponse, VideoGetCharacterResponse, VideoCreateCharacterResponse, ) from openai._utils import assert_signatures_in_sync from openai.pagination import SyncConversationCursorPage, AsyncConversationCursorPage # pyright: reportDeprecated=false base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestVideos: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: video = client.videos.create( prompt="x", ) assert_matches_type(Video, video, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: video = client.videos.create( prompt="x", input_reference=b"Example data", model="string", seconds="4", size="720x1280", ) assert_matches_type(Video, video, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.videos.with_raw_response.create( prompt="x", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(Video, video, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.videos.with_streaming_response.create( prompt="x", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(Video, video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_retrieve(self, client: OpenAI) -> None: video = client.videos.retrieve( "video_123", ) assert_matches_type(Video, video, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: response = client.videos.with_raw_response.retrieve( "video_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(Video, video, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with client.videos.with_streaming_response.retrieve( "video_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(Video, video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `video_id` but received ''"): client.videos.with_raw_response.retrieve( "", ) @parametrize def test_method_list(self, client: OpenAI) -> None: video = client.videos.list() assert_matches_type(SyncConversationCursorPage[Video], video, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: video = client.videos.list( after="after", limit=0, order="asc", ) assert_matches_type(SyncConversationCursorPage[Video], video, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.videos.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(SyncConversationCursorPage[Video], video, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.videos.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(SyncConversationCursorPage[Video], video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_delete(self, client: OpenAI) -> None: video = client.videos.delete( "video_123", ) assert_matches_type(VideoDeleteResponse, video, path=["response"]) @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: response = client.videos.with_raw_response.delete( "video_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(VideoDeleteResponse, video, path=["response"]) @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with client.videos.with_streaming_response.delete( "video_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(VideoDeleteResponse, video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `video_id` but received ''"): client.videos.with_raw_response.delete( "", ) @parametrize def test_method_create_character(self, client: OpenAI) -> None: video = client.videos.create_character( name="x", video=b"Example data", ) assert_matches_type(VideoCreateCharacterResponse, video, path=["response"]) @parametrize def test_raw_response_create_character(self, client: OpenAI) -> None: response = client.videos.with_raw_response.create_character( name="x", video=b"Example data", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(VideoCreateCharacterResponse, video, path=["response"]) @parametrize def test_streaming_response_create_character(self, client: OpenAI) -> None: with client.videos.with_streaming_response.create_character( name="x", video=b"Example data", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(VideoCreateCharacterResponse, video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize @pytest.mark.respx(base_url=base_url) def test_method_download_content(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/videos/video_123/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) video = client.videos.download_content( video_id="video_123", ) assert isinstance(video, _legacy_response.HttpxBinaryResponseContent) assert video.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) def test_method_download_content_with_all_params(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/videos/video_123/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) video = client.videos.download_content( video_id="video_123", variant="video", ) assert isinstance(video, _legacy_response.HttpxBinaryResponseContent) assert video.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) def test_raw_response_download_content(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/videos/video_123/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = client.videos.with_raw_response.download_content( video_id="video_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(_legacy_response.HttpxBinaryResponseContent, video, path=["response"]) @parametrize @pytest.mark.respx(base_url=base_url) def test_streaming_response_download_content(self, client: OpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/videos/video_123/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) with client.videos.with_streaming_response.download_content( video_id="video_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(bytes, video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize @pytest.mark.respx(base_url=base_url) def test_path_params_download_content(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `video_id` but received ''"): client.videos.with_raw_response.download_content( video_id="", ) @parametrize def test_method_edit(self, client: OpenAI) -> None: video = client.videos.edit( prompt="x", video=b"Example data", ) assert_matches_type(Video, video, path=["response"]) @parametrize def test_raw_response_edit(self, client: OpenAI) -> None: response = client.videos.with_raw_response.edit( prompt="x", video=b"Example data", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(Video, video, path=["response"]) @parametrize def test_streaming_response_edit(self, client: OpenAI) -> None: with client.videos.with_streaming_response.edit( prompt="x", video=b"Example data", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(Video, video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_extend(self, client: OpenAI) -> None: video = client.videos.extend( prompt="x", seconds="4", video=b"Example data", ) assert_matches_type(Video, video, path=["response"]) @parametrize def test_raw_response_extend(self, client: OpenAI) -> None: response = client.videos.with_raw_response.extend( prompt="x", seconds="4", video=b"Example data", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(Video, video, path=["response"]) @parametrize def test_streaming_response_extend(self, client: OpenAI) -> None: with client.videos.with_streaming_response.extend( prompt="x", seconds="4", video=b"Example data", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(Video, video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_get_character(self, client: OpenAI) -> None: video = client.videos.get_character( "char_123", ) assert_matches_type(VideoGetCharacterResponse, video, path=["response"]) @parametrize def test_raw_response_get_character(self, client: OpenAI) -> None: response = client.videos.with_raw_response.get_character( "char_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(VideoGetCharacterResponse, video, path=["response"]) @parametrize def test_streaming_response_get_character(self, client: OpenAI) -> None: with client.videos.with_streaming_response.get_character( "char_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(VideoGetCharacterResponse, video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_get_character(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `character_id` but received ''"): client.videos.with_raw_response.get_character( "", ) @parametrize def test_method_remix(self, client: OpenAI) -> None: video = client.videos.remix( video_id="video_123", prompt="x", ) assert_matches_type(Video, video, path=["response"]) @parametrize def test_raw_response_remix(self, client: OpenAI) -> None: response = client.videos.with_raw_response.remix( video_id="video_123", prompt="x", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(Video, video, path=["response"]) @parametrize def test_streaming_response_remix(self, client: OpenAI) -> None: with client.videos.with_streaming_response.remix( video_id="video_123", prompt="x", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(Video, video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_remix(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `video_id` but received ''"): client.videos.with_raw_response.remix( video_id="", prompt="x", ) class TestAsyncVideos: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: video = await async_client.videos.create( prompt="x", ) assert_matches_type(Video, video, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: video = await async_client.videos.create( prompt="x", input_reference=b"Example data", model="string", seconds="4", size="720x1280", ) assert_matches_type(Video, video, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.videos.with_raw_response.create( prompt="x", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(Video, video, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.videos.with_streaming_response.create( prompt="x", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = await response.parse() assert_matches_type(Video, video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: video = await async_client.videos.retrieve( "video_123", ) assert_matches_type(Video, video, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: response = await async_client.videos.with_raw_response.retrieve( "video_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(Video, video, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: async with async_client.videos.with_streaming_response.retrieve( "video_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = await response.parse() assert_matches_type(Video, video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `video_id` but received ''"): await async_client.videos.with_raw_response.retrieve( "", ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: video = await async_client.videos.list() assert_matches_type(AsyncConversationCursorPage[Video], video, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: video = await async_client.videos.list( after="after", limit=0, order="asc", ) assert_matches_type(AsyncConversationCursorPage[Video], video, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.videos.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(AsyncConversationCursorPage[Video], video, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.videos.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = await response.parse() assert_matches_type(AsyncConversationCursorPage[Video], video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: video = await async_client.videos.delete( "video_123", ) assert_matches_type(VideoDeleteResponse, video, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: response = await async_client.videos.with_raw_response.delete( "video_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(VideoDeleteResponse, video, path=["response"]) @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: async with async_client.videos.with_streaming_response.delete( "video_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = await response.parse() assert_matches_type(VideoDeleteResponse, video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `video_id` but received ''"): await async_client.videos.with_raw_response.delete( "", ) @parametrize async def test_method_create_character(self, async_client: AsyncOpenAI) -> None: video = await async_client.videos.create_character( name="x", video=b"Example data", ) assert_matches_type(VideoCreateCharacterResponse, video, path=["response"]) @parametrize async def test_raw_response_create_character(self, async_client: AsyncOpenAI) -> None: response = await async_client.videos.with_raw_response.create_character( name="x", video=b"Example data", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(VideoCreateCharacterResponse, video, path=["response"]) @parametrize async def test_streaming_response_create_character(self, async_client: AsyncOpenAI) -> None: async with async_client.videos.with_streaming_response.create_character( name="x", video=b"Example data", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = await response.parse() assert_matches_type(VideoCreateCharacterResponse, video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize @pytest.mark.respx(base_url=base_url) async def test_method_download_content(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/videos/video_123/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) video = await async_client.videos.download_content( video_id="video_123", ) assert isinstance(video, _legacy_response.HttpxBinaryResponseContent) assert video.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) async def test_method_download_content_with_all_params( self, async_client: AsyncOpenAI, respx_mock: MockRouter ) -> None: respx_mock.get("/videos/video_123/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) video = await async_client.videos.download_content( video_id="video_123", variant="video", ) assert isinstance(video, _legacy_response.HttpxBinaryResponseContent) assert video.json() == {"foo": "bar"} @parametrize @pytest.mark.respx(base_url=base_url) async def test_raw_response_download_content(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/videos/video_123/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = await async_client.videos.with_raw_response.download_content( video_id="video_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(_legacy_response.HttpxBinaryResponseContent, video, path=["response"]) @parametrize @pytest.mark.respx(base_url=base_url) async def test_streaming_response_download_content(self, async_client: AsyncOpenAI, respx_mock: MockRouter) -> None: respx_mock.get("/videos/video_123/content").mock(return_value=httpx.Response(200, json={"foo": "bar"})) async with async_client.videos.with_streaming_response.download_content( video_id="video_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = await response.parse() assert_matches_type(bytes, video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize @pytest.mark.respx(base_url=base_url) async def test_path_params_download_content(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `video_id` but received ''"): await async_client.videos.with_raw_response.download_content( video_id="", ) @parametrize async def test_method_edit(self, async_client: AsyncOpenAI) -> None: video = await async_client.videos.edit( prompt="x", video=b"Example data", ) assert_matches_type(Video, video, path=["response"]) @parametrize async def test_raw_response_edit(self, async_client: AsyncOpenAI) -> None: response = await async_client.videos.with_raw_response.edit( prompt="x", video=b"Example data", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(Video, video, path=["response"]) @parametrize async def test_streaming_response_edit(self, async_client: AsyncOpenAI) -> None: async with async_client.videos.with_streaming_response.edit( prompt="x", video=b"Example data", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = await response.parse() assert_matches_type(Video, video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_extend(self, async_client: AsyncOpenAI) -> None: video = await async_client.videos.extend( prompt="x", seconds="4", video=b"Example data", ) assert_matches_type(Video, video, path=["response"]) @parametrize async def test_raw_response_extend(self, async_client: AsyncOpenAI) -> None: response = await async_client.videos.with_raw_response.extend( prompt="x", seconds="4", video=b"Example data", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(Video, video, path=["response"]) @parametrize async def test_streaming_response_extend(self, async_client: AsyncOpenAI) -> None: async with async_client.videos.with_streaming_response.extend( prompt="x", seconds="4", video=b"Example data", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = await response.parse() assert_matches_type(Video, video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_get_character(self, async_client: AsyncOpenAI) -> None: video = await async_client.videos.get_character( "char_123", ) assert_matches_type(VideoGetCharacterResponse, video, path=["response"]) @parametrize async def test_raw_response_get_character(self, async_client: AsyncOpenAI) -> None: response = await async_client.videos.with_raw_response.get_character( "char_123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(VideoGetCharacterResponse, video, path=["response"]) @parametrize async def test_streaming_response_get_character(self, async_client: AsyncOpenAI) -> None: async with async_client.videos.with_streaming_response.get_character( "char_123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = await response.parse() assert_matches_type(VideoGetCharacterResponse, video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_get_character(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `character_id` but received ''"): await async_client.videos.with_raw_response.get_character( "", ) @parametrize async def test_method_remix(self, async_client: AsyncOpenAI) -> None: video = await async_client.videos.remix( video_id="video_123", prompt="x", ) assert_matches_type(Video, video, path=["response"]) @parametrize async def test_raw_response_remix(self, async_client: AsyncOpenAI) -> None: response = await async_client.videos.with_raw_response.remix( video_id="video_123", prompt="x", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = response.parse() assert_matches_type(Video, video, path=["response"]) @parametrize async def test_streaming_response_remix(self, async_client: AsyncOpenAI) -> None: async with async_client.videos.with_streaming_response.remix( video_id="video_123", prompt="x", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" video = await response.parse() assert_matches_type(Video, video, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_remix(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `video_id` but received ''"): await async_client.videos.with_raw_response.remix( video_id="", prompt="x", ) @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) def test_create_and_poll_method_in_sync(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: checking_client: OpenAI | AsyncOpenAI = client if sync else async_client assert_signatures_in_sync( checking_client.videos.create, checking_client.videos.create_and_poll, exclude_params={"extra_headers", "extra_query", "extra_body", "timeout"}, ) ================================================ FILE: tests/api_resources/test_webhooks.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from unittest import mock import pytest import openai from openai._exceptions import InvalidWebhookSignatureError base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") # Standardized test constants (matches TypeScript implementation) TEST_SECRET = "whsec_RdvaYFYUXuIFuEbvZHwMfYFhUf7aMYjYcmM24+Aj40c=" TEST_PAYLOAD = '{"id": "evt_685c059ae3a481909bdc86819b066fb6", "object": "event", "created_at": 1750861210, "type": "response.completed", "data": {"id": "resp_123"}}' TEST_TIMESTAMP = 1750861210 # Fixed timestamp that matches our test signature TEST_WEBHOOK_ID = "wh_685c059ae39c8190af8c71ed1022a24d" TEST_SIGNATURE = "v1,gUAg4R2hWouRZqRQG4uJypNS8YK885G838+EHb4nKBY=" def create_test_headers( timestamp: int | None = None, signature: str | None = None, webhook_id: str | None = None ) -> dict[str, str]: """Helper function to create test headers""" return { "webhook-signature": signature or TEST_SIGNATURE, "webhook-timestamp": str(timestamp or TEST_TIMESTAMP), "webhook-id": webhook_id or TEST_WEBHOOK_ID, } class TestWebhooks: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @mock.patch("time.time", mock.MagicMock(return_value=TEST_TIMESTAMP)) @parametrize def test_unwrap_with_secret(self, client: openai.OpenAI) -> None: headers = create_test_headers() unwrapped = client.webhooks.unwrap(TEST_PAYLOAD, headers, secret=TEST_SECRET) assert unwrapped.id == "evt_685c059ae3a481909bdc86819b066fb6" assert unwrapped.created_at == 1750861210 @parametrize def test_unwrap_without_secret(self, client: openai.OpenAI) -> None: headers = create_test_headers() with pytest.raises(ValueError, match="The webhook secret must either be set"): client.webhooks.unwrap(TEST_PAYLOAD, headers) @mock.patch("time.time", mock.MagicMock(return_value=TEST_TIMESTAMP)) @parametrize def test_verify_signature_valid(self, client: openai.OpenAI) -> None: headers = create_test_headers() # Should not raise - this is a truly valid signature for this timestamp client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=TEST_SECRET) @parametrize def test_verify_signature_invalid_secret_format(self, client: openai.OpenAI) -> None: headers = create_test_headers() with pytest.raises(ValueError, match="The webhook secret must either be set"): client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=None) @mock.patch("time.time", mock.MagicMock(return_value=TEST_TIMESTAMP)) @parametrize def test_verify_signature_invalid(self, client: openai.OpenAI) -> None: headers = create_test_headers() with pytest.raises(InvalidWebhookSignatureError, match="The given webhook signature does not match"): client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret="invalid_secret") @parametrize def test_verify_signature_missing_webhook_signature_header(self, client: openai.OpenAI) -> None: headers = create_test_headers(signature=None) del headers["webhook-signature"] with pytest.raises(ValueError, match="Could not find webhook-signature header"): client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=TEST_SECRET) @parametrize def test_verify_signature_missing_webhook_timestamp_header(self, client: openai.OpenAI) -> None: headers = create_test_headers() del headers["webhook-timestamp"] with pytest.raises(ValueError, match="Could not find webhook-timestamp header"): client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=TEST_SECRET) @parametrize def test_verify_signature_missing_webhook_id_header(self, client: openai.OpenAI) -> None: headers = create_test_headers() del headers["webhook-id"] with pytest.raises(ValueError, match="Could not find webhook-id header"): client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=TEST_SECRET) @mock.patch("time.time", mock.MagicMock(return_value=TEST_TIMESTAMP)) @parametrize def test_verify_signature_payload_bytes(self, client: openai.OpenAI) -> None: headers = create_test_headers() client.webhooks.verify_signature(TEST_PAYLOAD.encode("utf-8"), headers, secret=TEST_SECRET) @mock.patch("time.time", mock.MagicMock(return_value=TEST_TIMESTAMP)) def test_unwrap_with_client_secret(self) -> None: test_client = openai.OpenAI(base_url=base_url, api_key="test-api-key", webhook_secret=TEST_SECRET) headers = create_test_headers() unwrapped = test_client.webhooks.unwrap(TEST_PAYLOAD, headers) assert unwrapped.id == "evt_685c059ae3a481909bdc86819b066fb6" assert unwrapped.created_at == 1750861210 @parametrize def test_verify_signature_timestamp_too_old(self, client: openai.OpenAI) -> None: # Use a timestamp that's older than 5 minutes from our test timestamp old_timestamp = TEST_TIMESTAMP - 400 # 6 minutes 40 seconds ago headers = create_test_headers(timestamp=old_timestamp, signature="v1,dummy_signature") with pytest.raises(InvalidWebhookSignatureError, match="Webhook timestamp is too old"): client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=TEST_SECRET) @mock.patch("time.time", mock.MagicMock(return_value=TEST_TIMESTAMP)) @parametrize def test_verify_signature_timestamp_too_new(self, client: openai.OpenAI) -> None: # Use a timestamp that's in the future beyond tolerance from our test timestamp future_timestamp = TEST_TIMESTAMP + 400 # 6 minutes 40 seconds in the future headers = create_test_headers(timestamp=future_timestamp, signature="v1,dummy_signature") with pytest.raises(InvalidWebhookSignatureError, match="Webhook timestamp is too new"): client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=TEST_SECRET) @mock.patch("time.time", mock.MagicMock(return_value=TEST_TIMESTAMP)) @parametrize def test_verify_signature_custom_tolerance(self, client: openai.OpenAI) -> None: # Use a timestamp that's older than default tolerance but within custom tolerance old_timestamp = TEST_TIMESTAMP - 400 # 6 minutes 40 seconds ago from test timestamp headers = create_test_headers(timestamp=old_timestamp, signature="v1,dummy_signature") # Should fail with default tolerance with pytest.raises(InvalidWebhookSignatureError, match="Webhook timestamp is too old"): client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=TEST_SECRET) # Should also fail with custom tolerance of 10 minutes (signature won't match) with pytest.raises(InvalidWebhookSignatureError, match="The given webhook signature does not match"): client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=TEST_SECRET, tolerance=600) @mock.patch("time.time", mock.MagicMock(return_value=TEST_TIMESTAMP)) @parametrize def test_verify_signature_recent_timestamp_succeeds(self, client: openai.OpenAI) -> None: # Use a recent timestamp with dummy signature headers = create_test_headers(signature="v1,dummy_signature") # Should fail on signature verification (not timestamp validation) with pytest.raises(InvalidWebhookSignatureError, match="The given webhook signature does not match"): client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=TEST_SECRET) @mock.patch("time.time", mock.MagicMock(return_value=TEST_TIMESTAMP)) @parametrize def test_verify_signature_multiple_signatures_one_valid(self, client: openai.OpenAI) -> None: # Test multiple signatures: one invalid, one valid multiple_signatures = f"v1,invalid_signature {TEST_SIGNATURE}" headers = create_test_headers(signature=multiple_signatures) # Should not raise when at least one signature is valid client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=TEST_SECRET) @mock.patch("time.time", mock.MagicMock(return_value=TEST_TIMESTAMP)) @parametrize def test_verify_signature_multiple_signatures_all_invalid(self, client: openai.OpenAI) -> None: # Test multiple invalid signatures multiple_invalid_signatures = "v1,invalid_signature1 v1,invalid_signature2" headers = create_test_headers(signature=multiple_invalid_signatures) with pytest.raises(InvalidWebhookSignatureError, match="The given webhook signature does not match"): client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=TEST_SECRET) class TestAsyncWebhooks: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @mock.patch("time.time", mock.MagicMock(return_value=TEST_TIMESTAMP)) @parametrize async def test_unwrap_with_secret(self, async_client: openai.AsyncOpenAI) -> None: headers = create_test_headers() unwrapped = async_client.webhooks.unwrap(TEST_PAYLOAD, headers, secret=TEST_SECRET) assert unwrapped.id == "evt_685c059ae3a481909bdc86819b066fb6" assert unwrapped.created_at == 1750861210 @parametrize async def test_unwrap_without_secret(self, async_client: openai.AsyncOpenAI) -> None: headers = create_test_headers() with pytest.raises(ValueError, match="The webhook secret must either be set"): async_client.webhooks.unwrap(TEST_PAYLOAD, headers) @mock.patch("time.time", mock.MagicMock(return_value=TEST_TIMESTAMP)) @parametrize async def test_verify_signature_valid(self, async_client: openai.AsyncOpenAI) -> None: headers = create_test_headers() # Should not raise - this is a truly valid signature for this timestamp async_client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=TEST_SECRET) @parametrize async def test_verify_signature_invalid_secret_format(self, async_client: openai.AsyncOpenAI) -> None: headers = create_test_headers() with pytest.raises(ValueError, match="The webhook secret must either be set"): async_client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=None) @mock.patch("time.time", mock.MagicMock(return_value=TEST_TIMESTAMP)) @parametrize async def test_verify_signature_invalid(self, async_client: openai.AsyncOpenAI) -> None: headers = create_test_headers() with pytest.raises(InvalidWebhookSignatureError, match="The given webhook signature does not match"): async_client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret="invalid_secret") @parametrize async def test_verify_signature_missing_webhook_signature_header(self, async_client: openai.AsyncOpenAI) -> None: headers = create_test_headers() del headers["webhook-signature"] with pytest.raises(ValueError, match="Could not find webhook-signature header"): async_client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=TEST_SECRET) @parametrize async def test_verify_signature_missing_webhook_timestamp_header(self, async_client: openai.AsyncOpenAI) -> None: headers = create_test_headers() del headers["webhook-timestamp"] with pytest.raises(ValueError, match="Could not find webhook-timestamp header"): async_client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=TEST_SECRET) @parametrize async def test_verify_signature_missing_webhook_id_header(self, async_client: openai.AsyncOpenAI) -> None: headers = create_test_headers() del headers["webhook-id"] with pytest.raises(ValueError, match="Could not find webhook-id header"): async_client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=TEST_SECRET) @mock.patch("time.time", mock.MagicMock(return_value=TEST_TIMESTAMP)) @parametrize async def test_verify_signature_payload_bytes(self, async_client: openai.AsyncOpenAI) -> None: headers = create_test_headers() async_client.webhooks.verify_signature(TEST_PAYLOAD.encode("utf-8"), headers, secret=TEST_SECRET) @mock.patch("time.time", mock.MagicMock(return_value=TEST_TIMESTAMP)) async def test_unwrap_with_client_secret(self) -> None: test_async_client = openai.AsyncOpenAI(base_url=base_url, api_key="test-api-key", webhook_secret=TEST_SECRET) headers = create_test_headers() unwrapped = test_async_client.webhooks.unwrap(TEST_PAYLOAD, headers) assert unwrapped.id == "evt_685c059ae3a481909bdc86819b066fb6" assert unwrapped.created_at == 1750861210 @parametrize async def test_verify_signature_timestamp_too_old(self, async_client: openai.AsyncOpenAI) -> None: # Use a timestamp that's older than 5 minutes from our test timestamp old_timestamp = TEST_TIMESTAMP - 400 # 6 minutes 40 seconds ago headers = create_test_headers(timestamp=old_timestamp, signature="v1,dummy_signature") with pytest.raises(InvalidWebhookSignatureError, match="Webhook timestamp is too old"): async_client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=TEST_SECRET) @mock.patch("time.time", mock.MagicMock(return_value=TEST_TIMESTAMP)) @parametrize async def test_verify_signature_timestamp_too_new(self, async_client: openai.AsyncOpenAI) -> None: # Use a timestamp that's in the future beyond tolerance from our test timestamp future_timestamp = TEST_TIMESTAMP + 400 # 6 minutes 40 seconds in the future headers = create_test_headers(timestamp=future_timestamp, signature="v1,dummy_signature") with pytest.raises(InvalidWebhookSignatureError, match="Webhook timestamp is too new"): async_client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=TEST_SECRET) @mock.patch("time.time", mock.MagicMock(return_value=TEST_TIMESTAMP)) @parametrize async def test_verify_signature_multiple_signatures_one_valid(self, async_client: openai.AsyncOpenAI) -> None: # Test multiple signatures: one invalid, one valid multiple_signatures = f"v1,invalid_signature {TEST_SIGNATURE}" headers = create_test_headers(signature=multiple_signatures) # Should not raise when at least one signature is valid async_client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=TEST_SECRET) @mock.patch("time.time", mock.MagicMock(return_value=TEST_TIMESTAMP)) @parametrize async def test_verify_signature_multiple_signatures_all_invalid(self, async_client: openai.AsyncOpenAI) -> None: # Test multiple invalid signatures multiple_invalid_signatures = "v1,invalid_signature1 v1,invalid_signature2" headers = create_test_headers(signature=multiple_invalid_signatures) with pytest.raises(InvalidWebhookSignatureError, match="The given webhook signature does not match"): async_client.webhooks.verify_signature(TEST_PAYLOAD, headers, secret=TEST_SECRET) ================================================ FILE: tests/api_resources/uploads/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/uploads/test_parts.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai.types.uploads import UploadPart base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestParts: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: part = client.uploads.parts.create( upload_id="upload_abc123", data=b"Example data", ) assert_matches_type(UploadPart, part, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.uploads.parts.with_raw_response.create( upload_id="upload_abc123", data=b"Example data", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" part = response.parse() assert_matches_type(UploadPart, part, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.uploads.parts.with_streaming_response.create( upload_id="upload_abc123", data=b"Example data", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" part = response.parse() assert_matches_type(UploadPart, part, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_create(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `upload_id` but received ''"): client.uploads.parts.with_raw_response.create( upload_id="", data=b"Example data", ) class TestAsyncParts: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: part = await async_client.uploads.parts.create( upload_id="upload_abc123", data=b"Example data", ) assert_matches_type(UploadPart, part, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.uploads.parts.with_raw_response.create( upload_id="upload_abc123", data=b"Example data", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" part = response.parse() assert_matches_type(UploadPart, part, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.uploads.parts.with_streaming_response.create( upload_id="upload_abc123", data=b"Example data", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" part = await response.parse() assert_matches_type(UploadPart, part, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_create(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `upload_id` but received ''"): await async_client.uploads.parts.with_raw_response.create( upload_id="", data=b"Example data", ) ================================================ FILE: tests/api_resources/vector_stores/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/api_resources/vector_stores/test_file_batches.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai._utils import assert_signatures_in_sync from openai.pagination import SyncCursorPage, AsyncCursorPage from openai.types.vector_stores import ( VectorStoreFile, VectorStoreFileBatch, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestFileBatches: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: file_batch = client.vector_stores.file_batches.create( vector_store_id="vs_abc123", ) assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: file_batch = client.vector_stores.file_batches.create( vector_store_id="vs_abc123", attributes={"foo": "string"}, chunking_strategy={"type": "auto"}, file_ids=["string"], files=[ { "file_id": "file_id", "attributes": {"foo": "string"}, "chunking_strategy": {"type": "auto"}, } ], ) assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.vector_stores.file_batches.with_raw_response.create( vector_store_id="vs_abc123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file_batch = response.parse() assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.vector_stores.file_batches.with_streaming_response.create( vector_store_id="vs_abc123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file_batch = response.parse() assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_create(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): client.vector_stores.file_batches.with_raw_response.create( vector_store_id="", ) @parametrize def test_method_retrieve(self, client: OpenAI) -> None: file_batch = client.vector_stores.file_batches.retrieve( batch_id="vsfb_abc123", vector_store_id="vs_abc123", ) assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: response = client.vector_stores.file_batches.with_raw_response.retrieve( batch_id="vsfb_abc123", vector_store_id="vs_abc123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file_batch = response.parse() assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with client.vector_stores.file_batches.with_streaming_response.retrieve( batch_id="vsfb_abc123", vector_store_id="vs_abc123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file_batch = response.parse() assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): client.vector_stores.file_batches.with_raw_response.retrieve( batch_id="vsfb_abc123", vector_store_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `batch_id` but received ''"): client.vector_stores.file_batches.with_raw_response.retrieve( batch_id="", vector_store_id="vs_abc123", ) @parametrize def test_method_cancel(self, client: OpenAI) -> None: file_batch = client.vector_stores.file_batches.cancel( batch_id="batch_id", vector_store_id="vector_store_id", ) assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) @parametrize def test_raw_response_cancel(self, client: OpenAI) -> None: response = client.vector_stores.file_batches.with_raw_response.cancel( batch_id="batch_id", vector_store_id="vector_store_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file_batch = response.parse() assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) @parametrize def test_streaming_response_cancel(self, client: OpenAI) -> None: with client.vector_stores.file_batches.with_streaming_response.cancel( batch_id="batch_id", vector_store_id="vector_store_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file_batch = response.parse() assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_cancel(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): client.vector_stores.file_batches.with_raw_response.cancel( batch_id="batch_id", vector_store_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `batch_id` but received ''"): client.vector_stores.file_batches.with_raw_response.cancel( batch_id="", vector_store_id="vector_store_id", ) @parametrize def test_method_list_files(self, client: OpenAI) -> None: file_batch = client.vector_stores.file_batches.list_files( batch_id="batch_id", vector_store_id="vector_store_id", ) assert_matches_type(SyncCursorPage[VectorStoreFile], file_batch, path=["response"]) @parametrize def test_method_list_files_with_all_params(self, client: OpenAI) -> None: file_batch = client.vector_stores.file_batches.list_files( batch_id="batch_id", vector_store_id="vector_store_id", after="after", before="before", filter="in_progress", limit=0, order="asc", ) assert_matches_type(SyncCursorPage[VectorStoreFile], file_batch, path=["response"]) @parametrize def test_raw_response_list_files(self, client: OpenAI) -> None: response = client.vector_stores.file_batches.with_raw_response.list_files( batch_id="batch_id", vector_store_id="vector_store_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file_batch = response.parse() assert_matches_type(SyncCursorPage[VectorStoreFile], file_batch, path=["response"]) @parametrize def test_streaming_response_list_files(self, client: OpenAI) -> None: with client.vector_stores.file_batches.with_streaming_response.list_files( batch_id="batch_id", vector_store_id="vector_store_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file_batch = response.parse() assert_matches_type(SyncCursorPage[VectorStoreFile], file_batch, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_list_files(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): client.vector_stores.file_batches.with_raw_response.list_files( batch_id="batch_id", vector_store_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `batch_id` but received ''"): client.vector_stores.file_batches.with_raw_response.list_files( batch_id="", vector_store_id="vector_store_id", ) class TestAsyncFileBatches: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: file_batch = await async_client.vector_stores.file_batches.create( vector_store_id="vs_abc123", ) assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: file_batch = await async_client.vector_stores.file_batches.create( vector_store_id="vs_abc123", attributes={"foo": "string"}, chunking_strategy={"type": "auto"}, file_ids=["string"], files=[ { "file_id": "file_id", "attributes": {"foo": "string"}, "chunking_strategy": {"type": "auto"}, } ], ) assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.vector_stores.file_batches.with_raw_response.create( vector_store_id="vs_abc123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file_batch = response.parse() assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.vector_stores.file_batches.with_streaming_response.create( vector_store_id="vs_abc123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file_batch = await response.parse() assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_create(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): await async_client.vector_stores.file_batches.with_raw_response.create( vector_store_id="", ) @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: file_batch = await async_client.vector_stores.file_batches.retrieve( batch_id="vsfb_abc123", vector_store_id="vs_abc123", ) assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: response = await async_client.vector_stores.file_batches.with_raw_response.retrieve( batch_id="vsfb_abc123", vector_store_id="vs_abc123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file_batch = response.parse() assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: async with async_client.vector_stores.file_batches.with_streaming_response.retrieve( batch_id="vsfb_abc123", vector_store_id="vs_abc123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file_batch = await response.parse() assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): await async_client.vector_stores.file_batches.with_raw_response.retrieve( batch_id="vsfb_abc123", vector_store_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `batch_id` but received ''"): await async_client.vector_stores.file_batches.with_raw_response.retrieve( batch_id="", vector_store_id="vs_abc123", ) @parametrize async def test_method_cancel(self, async_client: AsyncOpenAI) -> None: file_batch = await async_client.vector_stores.file_batches.cancel( batch_id="batch_id", vector_store_id="vector_store_id", ) assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) @parametrize async def test_raw_response_cancel(self, async_client: AsyncOpenAI) -> None: response = await async_client.vector_stores.file_batches.with_raw_response.cancel( batch_id="batch_id", vector_store_id="vector_store_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file_batch = response.parse() assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) @parametrize async def test_streaming_response_cancel(self, async_client: AsyncOpenAI) -> None: async with async_client.vector_stores.file_batches.with_streaming_response.cancel( batch_id="batch_id", vector_store_id="vector_store_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file_batch = await response.parse() assert_matches_type(VectorStoreFileBatch, file_batch, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_cancel(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): await async_client.vector_stores.file_batches.with_raw_response.cancel( batch_id="batch_id", vector_store_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `batch_id` but received ''"): await async_client.vector_stores.file_batches.with_raw_response.cancel( batch_id="", vector_store_id="vector_store_id", ) @parametrize async def test_method_list_files(self, async_client: AsyncOpenAI) -> None: file_batch = await async_client.vector_stores.file_batches.list_files( batch_id="batch_id", vector_store_id="vector_store_id", ) assert_matches_type(AsyncCursorPage[VectorStoreFile], file_batch, path=["response"]) @parametrize async def test_method_list_files_with_all_params(self, async_client: AsyncOpenAI) -> None: file_batch = await async_client.vector_stores.file_batches.list_files( batch_id="batch_id", vector_store_id="vector_store_id", after="after", before="before", filter="in_progress", limit=0, order="asc", ) assert_matches_type(AsyncCursorPage[VectorStoreFile], file_batch, path=["response"]) @parametrize async def test_raw_response_list_files(self, async_client: AsyncOpenAI) -> None: response = await async_client.vector_stores.file_batches.with_raw_response.list_files( batch_id="batch_id", vector_store_id="vector_store_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file_batch = response.parse() assert_matches_type(AsyncCursorPage[VectorStoreFile], file_batch, path=["response"]) @parametrize async def test_streaming_response_list_files(self, async_client: AsyncOpenAI) -> None: async with async_client.vector_stores.file_batches.with_streaming_response.list_files( batch_id="batch_id", vector_store_id="vector_store_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file_batch = await response.parse() assert_matches_type(AsyncCursorPage[VectorStoreFile], file_batch, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_list_files(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): await async_client.vector_stores.file_batches.with_raw_response.list_files( batch_id="batch_id", vector_store_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `batch_id` but received ''"): await async_client.vector_stores.file_batches.with_raw_response.list_files( batch_id="", vector_store_id="vector_store_id", ) @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) def test_create_and_poll_method_in_sync(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: checking_client: OpenAI | AsyncOpenAI = client if sync else async_client # ensure helpers do not drift from generated spec assert_signatures_in_sync( checking_client.vector_stores.file_batches.create, checking_client.vector_stores.file_batches.create_and_poll, ) ================================================ FILE: tests/api_resources/vector_stores/test_files.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os from typing import Any, cast import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import assert_matches_type from openai._utils import assert_signatures_in_sync from openai.pagination import SyncPage, AsyncPage, SyncCursorPage, AsyncCursorPage from openai.types.vector_stores import ( VectorStoreFile, FileContentResponse, VectorStoreFileDeleted, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") class TestFiles: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize def test_method_create(self, client: OpenAI) -> None: file = client.vector_stores.files.create( vector_store_id="vs_abc123", file_id="file_id", ) assert_matches_type(VectorStoreFile, file, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: OpenAI) -> None: file = client.vector_stores.files.create( vector_store_id="vs_abc123", file_id="file_id", attributes={"foo": "string"}, chunking_strategy={"type": "auto"}, ) assert_matches_type(VectorStoreFile, file, path=["response"]) @parametrize def test_raw_response_create(self, client: OpenAI) -> None: response = client.vector_stores.files.with_raw_response.create( vector_store_id="vs_abc123", file_id="file_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(VectorStoreFile, file, path=["response"]) @parametrize def test_streaming_response_create(self, client: OpenAI) -> None: with client.vector_stores.files.with_streaming_response.create( vector_store_id="vs_abc123", file_id="file_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(VectorStoreFile, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_create(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): client.vector_stores.files.with_raw_response.create( vector_store_id="", file_id="file_id", ) @parametrize def test_method_retrieve(self, client: OpenAI) -> None: file = client.vector_stores.files.retrieve( file_id="file-abc123", vector_store_id="vs_abc123", ) assert_matches_type(VectorStoreFile, file, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: OpenAI) -> None: response = client.vector_stores.files.with_raw_response.retrieve( file_id="file-abc123", vector_store_id="vs_abc123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(VectorStoreFile, file, path=["response"]) @parametrize def test_streaming_response_retrieve(self, client: OpenAI) -> None: with client.vector_stores.files.with_streaming_response.retrieve( file_id="file-abc123", vector_store_id="vs_abc123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(VectorStoreFile, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): client.vector_stores.files.with_raw_response.retrieve( file_id="file-abc123", vector_store_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): client.vector_stores.files.with_raw_response.retrieve( file_id="", vector_store_id="vs_abc123", ) @parametrize def test_method_update(self, client: OpenAI) -> None: file = client.vector_stores.files.update( file_id="file-abc123", vector_store_id="vs_abc123", attributes={"foo": "string"}, ) assert_matches_type(VectorStoreFile, file, path=["response"]) @parametrize def test_raw_response_update(self, client: OpenAI) -> None: response = client.vector_stores.files.with_raw_response.update( file_id="file-abc123", vector_store_id="vs_abc123", attributes={"foo": "string"}, ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(VectorStoreFile, file, path=["response"]) @parametrize def test_streaming_response_update(self, client: OpenAI) -> None: with client.vector_stores.files.with_streaming_response.update( file_id="file-abc123", vector_store_id="vs_abc123", attributes={"foo": "string"}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(VectorStoreFile, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_update(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): client.vector_stores.files.with_raw_response.update( file_id="file-abc123", vector_store_id="", attributes={"foo": "string"}, ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): client.vector_stores.files.with_raw_response.update( file_id="", vector_store_id="vs_abc123", attributes={"foo": "string"}, ) @parametrize def test_method_list(self, client: OpenAI) -> None: file = client.vector_stores.files.list( vector_store_id="vector_store_id", ) assert_matches_type(SyncCursorPage[VectorStoreFile], file, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: OpenAI) -> None: file = client.vector_stores.files.list( vector_store_id="vector_store_id", after="after", before="before", filter="in_progress", limit=0, order="asc", ) assert_matches_type(SyncCursorPage[VectorStoreFile], file, path=["response"]) @parametrize def test_raw_response_list(self, client: OpenAI) -> None: response = client.vector_stores.files.with_raw_response.list( vector_store_id="vector_store_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(SyncCursorPage[VectorStoreFile], file, path=["response"]) @parametrize def test_streaming_response_list(self, client: OpenAI) -> None: with client.vector_stores.files.with_streaming_response.list( vector_store_id="vector_store_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(SyncCursorPage[VectorStoreFile], file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_list(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): client.vector_stores.files.with_raw_response.list( vector_store_id="", ) @parametrize def test_method_delete(self, client: OpenAI) -> None: file = client.vector_stores.files.delete( file_id="file_id", vector_store_id="vector_store_id", ) assert_matches_type(VectorStoreFileDeleted, file, path=["response"]) @parametrize def test_raw_response_delete(self, client: OpenAI) -> None: response = client.vector_stores.files.with_raw_response.delete( file_id="file_id", vector_store_id="vector_store_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(VectorStoreFileDeleted, file, path=["response"]) @parametrize def test_streaming_response_delete(self, client: OpenAI) -> None: with client.vector_stores.files.with_streaming_response.delete( file_id="file_id", vector_store_id="vector_store_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(VectorStoreFileDeleted, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): client.vector_stores.files.with_raw_response.delete( file_id="file_id", vector_store_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): client.vector_stores.files.with_raw_response.delete( file_id="", vector_store_id="vector_store_id", ) @parametrize def test_method_content(self, client: OpenAI) -> None: file = client.vector_stores.files.content( file_id="file-abc123", vector_store_id="vs_abc123", ) assert_matches_type(SyncPage[FileContentResponse], file, path=["response"]) @parametrize def test_raw_response_content(self, client: OpenAI) -> None: response = client.vector_stores.files.with_raw_response.content( file_id="file-abc123", vector_store_id="vs_abc123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(SyncPage[FileContentResponse], file, path=["response"]) @parametrize def test_streaming_response_content(self, client: OpenAI) -> None: with client.vector_stores.files.with_streaming_response.content( file_id="file-abc123", vector_store_id="vs_abc123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(SyncPage[FileContentResponse], file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_content(self, client: OpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): client.vector_stores.files.with_raw_response.content( file_id="file-abc123", vector_store_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): client.vector_stores.files.with_raw_response.content( file_id="", vector_store_id="vs_abc123", ) class TestAsyncFiles: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @parametrize async def test_method_create(self, async_client: AsyncOpenAI) -> None: file = await async_client.vector_stores.files.create( vector_store_id="vs_abc123", file_id="file_id", ) assert_matches_type(VectorStoreFile, file, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None: file = await async_client.vector_stores.files.create( vector_store_id="vs_abc123", file_id="file_id", attributes={"foo": "string"}, chunking_strategy={"type": "auto"}, ) assert_matches_type(VectorStoreFile, file, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: response = await async_client.vector_stores.files.with_raw_response.create( vector_store_id="vs_abc123", file_id="file_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(VectorStoreFile, file, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: async with async_client.vector_stores.files.with_streaming_response.create( vector_store_id="vs_abc123", file_id="file_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() assert_matches_type(VectorStoreFile, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_create(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): await async_client.vector_stores.files.with_raw_response.create( vector_store_id="", file_id="file_id", ) @parametrize async def test_method_retrieve(self, async_client: AsyncOpenAI) -> None: file = await async_client.vector_stores.files.retrieve( file_id="file-abc123", vector_store_id="vs_abc123", ) assert_matches_type(VectorStoreFile, file, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None: response = await async_client.vector_stores.files.with_raw_response.retrieve( file_id="file-abc123", vector_store_id="vs_abc123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(VectorStoreFile, file, path=["response"]) @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None: async with async_client.vector_stores.files.with_streaming_response.retrieve( file_id="file-abc123", vector_store_id="vs_abc123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() assert_matches_type(VectorStoreFile, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): await async_client.vector_stores.files.with_raw_response.retrieve( file_id="file-abc123", vector_store_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): await async_client.vector_stores.files.with_raw_response.retrieve( file_id="", vector_store_id="vs_abc123", ) @parametrize async def test_method_update(self, async_client: AsyncOpenAI) -> None: file = await async_client.vector_stores.files.update( file_id="file-abc123", vector_store_id="vs_abc123", attributes={"foo": "string"}, ) assert_matches_type(VectorStoreFile, file, path=["response"]) @parametrize async def test_raw_response_update(self, async_client: AsyncOpenAI) -> None: response = await async_client.vector_stores.files.with_raw_response.update( file_id="file-abc123", vector_store_id="vs_abc123", attributes={"foo": "string"}, ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(VectorStoreFile, file, path=["response"]) @parametrize async def test_streaming_response_update(self, async_client: AsyncOpenAI) -> None: async with async_client.vector_stores.files.with_streaming_response.update( file_id="file-abc123", vector_store_id="vs_abc123", attributes={"foo": "string"}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() assert_matches_type(VectorStoreFile, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_update(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): await async_client.vector_stores.files.with_raw_response.update( file_id="file-abc123", vector_store_id="", attributes={"foo": "string"}, ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): await async_client.vector_stores.files.with_raw_response.update( file_id="", vector_store_id="vs_abc123", attributes={"foo": "string"}, ) @parametrize async def test_method_list(self, async_client: AsyncOpenAI) -> None: file = await async_client.vector_stores.files.list( vector_store_id="vector_store_id", ) assert_matches_type(AsyncCursorPage[VectorStoreFile], file, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOpenAI) -> None: file = await async_client.vector_stores.files.list( vector_store_id="vector_store_id", after="after", before="before", filter="in_progress", limit=0, order="asc", ) assert_matches_type(AsyncCursorPage[VectorStoreFile], file, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncOpenAI) -> None: response = await async_client.vector_stores.files.with_raw_response.list( vector_store_id="vector_store_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(AsyncCursorPage[VectorStoreFile], file, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncOpenAI) -> None: async with async_client.vector_stores.files.with_streaming_response.list( vector_store_id="vector_store_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() assert_matches_type(AsyncCursorPage[VectorStoreFile], file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_list(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): await async_client.vector_stores.files.with_raw_response.list( vector_store_id="", ) @parametrize async def test_method_delete(self, async_client: AsyncOpenAI) -> None: file = await async_client.vector_stores.files.delete( file_id="file_id", vector_store_id="vector_store_id", ) assert_matches_type(VectorStoreFileDeleted, file, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncOpenAI) -> None: response = await async_client.vector_stores.files.with_raw_response.delete( file_id="file_id", vector_store_id="vector_store_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(VectorStoreFileDeleted, file, path=["response"]) @parametrize async def test_streaming_response_delete(self, async_client: AsyncOpenAI) -> None: async with async_client.vector_stores.files.with_streaming_response.delete( file_id="file_id", vector_store_id="vector_store_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() assert_matches_type(VectorStoreFileDeleted, file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): await async_client.vector_stores.files.with_raw_response.delete( file_id="file_id", vector_store_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): await async_client.vector_stores.files.with_raw_response.delete( file_id="", vector_store_id="vector_store_id", ) @parametrize async def test_method_content(self, async_client: AsyncOpenAI) -> None: file = await async_client.vector_stores.files.content( file_id="file-abc123", vector_store_id="vs_abc123", ) assert_matches_type(AsyncPage[FileContentResponse], file, path=["response"]) @parametrize async def test_raw_response_content(self, async_client: AsyncOpenAI) -> None: response = await async_client.vector_stores.files.with_raw_response.content( file_id="file-abc123", vector_store_id="vs_abc123", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() assert_matches_type(AsyncPage[FileContentResponse], file, path=["response"]) @parametrize async def test_streaming_response_content(self, async_client: AsyncOpenAI) -> None: async with async_client.vector_stores.files.with_streaming_response.content( file_id="file-abc123", vector_store_id="vs_abc123", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() assert_matches_type(AsyncPage[FileContentResponse], file, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_content(self, async_client: AsyncOpenAI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): await async_client.vector_stores.files.with_raw_response.content( file_id="file-abc123", vector_store_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): await async_client.vector_stores.files.with_raw_response.content( file_id="", vector_store_id="vs_abc123", ) @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) def test_create_and_poll_method_in_sync(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: checking_client: OpenAI | AsyncOpenAI = client if sync else async_client assert_signatures_in_sync( checking_client.vector_stores.files.create, checking_client.vector_stores.files.create_and_poll, ) @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) def test_upload_and_poll_method_in_sync(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: checking_client: OpenAI | AsyncOpenAI = client if sync else async_client assert_signatures_in_sync( checking_client.vector_stores.files.create, checking_client.vector_stores.files.upload_and_poll, exclude_params={"file_id", "extra_headers", "extra_query", "extra_body", "timeout"}, ) ================================================ FILE: tests/api_resources/webhooks/__init__.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. ================================================ FILE: tests/compat/test_tool_param.py ================================================ from openai.types.chat import ChatCompletionToolParam def test_tool_param_can_be_instantiated() -> None: assert ChatCompletionToolParam(type="function", function={"name": "test"}) == { "function": {"name": "test"}, "type": "function", } ================================================ FILE: tests/conftest.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os import logging from typing import TYPE_CHECKING, Iterator, AsyncIterator import httpx import pytest from pytest_asyncio import is_async_test from openai import OpenAI, AsyncOpenAI, DefaultAioHttpClient from openai._utils import is_dict if TYPE_CHECKING: from _pytest.fixtures import FixtureRequest # pyright: ignore[reportPrivateImportUsage] pytest.register_assert_rewrite("tests.utils") logging.getLogger("openai").setLevel(logging.DEBUG) # automatically add `pytest.mark.asyncio()` to all of our async tests # so we don't have to add that boilerplate everywhere def pytest_collection_modifyitems(items: list[pytest.Function]) -> None: pytest_asyncio_tests = (item for item in items if is_async_test(item)) session_scope_marker = pytest.mark.asyncio(loop_scope="session") for async_test in pytest_asyncio_tests: async_test.add_marker(session_scope_marker, append=False) # We skip tests that use both the aiohttp client and respx_mock as respx_mock # doesn't support custom transports. for item in items: if "async_client" not in item.fixturenames or "respx_mock" not in item.fixturenames: continue if not hasattr(item, "callspec"): continue async_client_param = item.callspec.params.get("async_client") if is_dict(async_client_param) and async_client_param.get("http_client") == "aiohttp": item.add_marker(pytest.mark.skip(reason="aiohttp client is not compatible with respx_mock")) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") api_key = "My API Key" @pytest.fixture(scope="session") def client(request: FixtureRequest) -> Iterator[OpenAI]: strict = getattr(request, "param", True) if not isinstance(strict, bool): raise TypeError(f"Unexpected fixture parameter type {type(strict)}, expected {bool}") with OpenAI(base_url=base_url, api_key=api_key, _strict_response_validation=strict) as client: yield client @pytest.fixture(scope="session") async def async_client(request: FixtureRequest) -> AsyncIterator[AsyncOpenAI]: param = getattr(request, "param", True) # defaults strict = True http_client: None | httpx.AsyncClient = None if isinstance(param, bool): strict = param elif is_dict(param): strict = param.get("strict", True) assert isinstance(strict, bool) http_client_type = param.get("http_client", "httpx") if http_client_type == "aiohttp": http_client = DefaultAioHttpClient() else: raise TypeError(f"Unexpected fixture parameter type {type(param)}, expected bool or dict") async with AsyncOpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=strict, http_client=http_client ) as client: yield client ================================================ FILE: tests/lib/__init__.py ================================================ ================================================ FILE: tests/lib/chat/__init__.py ================================================ ================================================ FILE: tests/lib/chat/test_completions.py ================================================ from __future__ import annotations from enum import Enum from typing import List, Optional from typing_extensions import Literal, TypeVar import pytest from respx import MockRouter from pydantic import Field, BaseModel from inline_snapshot import snapshot import openai from openai import OpenAI, AsyncOpenAI from openai._utils import assert_signatures_in_sync from openai._compat import PYDANTIC_V1 from ..utils import print_obj from ...conftest import base_url from ..snapshots import make_snapshot_request, make_async_snapshot_request from ..schema_types.query import Query _T = TypeVar("_T") # all the snapshots in this file are auto-generated from the live API # # you can update them with # # `OPENAI_LIVE=1 pytest --inline-snapshot=fix -p no:xdist -o addopts=""` @pytest.mark.respx(base_url=base_url) def test_parse_nothing(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: completion = make_snapshot_request( lambda c: c.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in SF?", }, ], ), content_snapshot=snapshot( '{"id": "chatcmpl-ABfvaueLEMLNYbT8YzpJxsmiQ6HSY", "object": "chat.completion", "created": 1727346142, "model": "gpt-4o-2024-08-06", "choices": [{"index": 0, "message": {"role": "assistant", "content": "I\'m unable to provide real-time weather updates. To get the current weather in San Francisco, I recommend checking a reliable weather website or app like the Weather Channel or a local news station.", "refusal": null}, "logprobs": null, "finish_reason": "stop"}], "usage": {"prompt_tokens": 14, "completion_tokens": 37, "total_tokens": 51, "completion_tokens_details": {"reasoning_tokens": 0}}, "system_fingerprint": "fp_b40fb1c6fb"}' ), path="/chat/completions", mock_client=client, respx_mock=respx_mock, ) assert print_obj(completion, monkeypatch) == snapshot( """\ ParsedChatCompletion( choices=[ ParsedChoice( finish_reason='stop', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content="I'm unable to provide real-time weather updates. To get the current weather in San Francisco, I recommend checking a reliable weather website or app like the Weather Channel or a local news station.", function_call=None, parsed=None, refusal=None, role='assistant', tool_calls=None ) ) ], created=1727346142, id='chatcmpl-ABfvaueLEMLNYbT8YzpJxsmiQ6HSY', model='gpt-4o-2024-08-06', object='chat.completion', service_tier=None, system_fingerprint='fp_b40fb1c6fb', usage=CompletionUsage( completion_tokens=37, completion_tokens_details=CompletionTokensDetails( accepted_prediction_tokens=None, audio_tokens=None, reasoning_tokens=0, rejected_prediction_tokens=None ), prompt_tokens=14, prompt_tokens_details=None, total_tokens=51 ) ) """ ) @pytest.mark.respx(base_url=base_url) def test_parse_pydantic_model(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: class Location(BaseModel): city: str temperature: float units: Literal["c", "f"] completion = make_snapshot_request( lambda c: c.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in SF?", }, ], response_format=Location, ), content_snapshot=snapshot( '{"id": "chatcmpl-ABfvbtVnTu5DeC4EFnRYj8mtfOM99", "object": "chat.completion", "created": 1727346143, "model": "gpt-4o-2024-08-06", "choices": [{"index": 0, "message": {"role": "assistant", "content": "{\\"city\\":\\"San Francisco\\",\\"temperature\\":65,\\"units\\":\\"f\\"}", "refusal": null}, "logprobs": null, "finish_reason": "stop"}], "usage": {"prompt_tokens": 79, "completion_tokens": 14, "total_tokens": 93, "completion_tokens_details": {"reasoning_tokens": 0}}, "system_fingerprint": "fp_5050236cbd"}' ), path="/chat/completions", mock_client=client, respx_mock=respx_mock, ) assert print_obj(completion, monkeypatch) == snapshot( """\ ParsedChatCompletion( choices=[ ParsedChoice( finish_reason='stop', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content='{"city":"San Francisco","temperature":65,"units":"f"}', function_call=None, parsed=Location(city='San Francisco', temperature=65.0, units='f'), refusal=None, role='assistant', tool_calls=None ) ) ], created=1727346143, id='chatcmpl-ABfvbtVnTu5DeC4EFnRYj8mtfOM99', model='gpt-4o-2024-08-06', object='chat.completion', service_tier=None, system_fingerprint='fp_5050236cbd', usage=CompletionUsage( completion_tokens=14, completion_tokens_details=CompletionTokensDetails( accepted_prediction_tokens=None, audio_tokens=None, reasoning_tokens=0, rejected_prediction_tokens=None ), prompt_tokens=79, prompt_tokens_details=None, total_tokens=93 ) ) """ ) @pytest.mark.respx(base_url=base_url) def test_parse_pydantic_model_optional_default( client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch ) -> None: class Location(BaseModel): city: str temperature: float units: Optional[Literal["c", "f"]] = None completion = make_snapshot_request( lambda c: c.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in SF?", }, ], response_format=Location, ), content_snapshot=snapshot( '{"id": "chatcmpl-ABfvcC8grKYsRkSoMp9CCAhbXAd0b", "object": "chat.completion", "created": 1727346144, "model": "gpt-4o-2024-08-06", "choices": [{"index": 0, "message": {"role": "assistant", "content": "{\\"city\\":\\"San Francisco\\",\\"temperature\\":65,\\"units\\":\\"f\\"}", "refusal": null}, "logprobs": null, "finish_reason": "stop"}], "usage": {"prompt_tokens": 88, "completion_tokens": 14, "total_tokens": 102, "completion_tokens_details": {"reasoning_tokens": 0}}, "system_fingerprint": "fp_b40fb1c6fb"}' ), path="/chat/completions", mock_client=client, respx_mock=respx_mock, ) assert print_obj(completion, monkeypatch) == snapshot( """\ ParsedChatCompletion( choices=[ ParsedChoice( finish_reason='stop', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content='{"city":"San Francisco","temperature":65,"units":"f"}', function_call=None, parsed=Location(city='San Francisco', temperature=65.0, units='f'), refusal=None, role='assistant', tool_calls=None ) ) ], created=1727346144, id='chatcmpl-ABfvcC8grKYsRkSoMp9CCAhbXAd0b', model='gpt-4o-2024-08-06', object='chat.completion', service_tier=None, system_fingerprint='fp_b40fb1c6fb', usage=CompletionUsage( completion_tokens=14, completion_tokens_details=CompletionTokensDetails( accepted_prediction_tokens=None, audio_tokens=None, reasoning_tokens=0, rejected_prediction_tokens=None ), prompt_tokens=88, prompt_tokens_details=None, total_tokens=102 ) ) """ ) @pytest.mark.respx(base_url=base_url) def test_parse_pydantic_model_enum(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: class Color(Enum): """The detected color""" RED = "red" BLUE = "blue" GREEN = "green" class ColorDetection(BaseModel): color: Color hex_color_code: str = Field(description="The hex color code of the detected color") if PYDANTIC_V1: ColorDetection.update_forward_refs(**locals()) # type: ignore completion = make_snapshot_request( lambda c: c.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[ {"role": "user", "content": "What color is a Coke can?"}, ], response_format=ColorDetection, ), content_snapshot=snapshot( '{"id": "chatcmpl-ABfvjIatz0zrZu50gRbMtlp0asZpz", "object": "chat.completion", "created": 1727346151, "model": "gpt-4o-2024-08-06", "choices": [{"index": 0, "message": {"role": "assistant", "content": "{\\"color\\":\\"red\\",\\"hex_color_code\\":\\"#FF0000\\"}", "refusal": null}, "logprobs": null, "finish_reason": "stop"}], "usage": {"prompt_tokens": 109, "completion_tokens": 14, "total_tokens": 123, "completion_tokens_details": {"reasoning_tokens": 0}}, "system_fingerprint": "fp_5050236cbd"}' ), path="/chat/completions", mock_client=client, respx_mock=respx_mock, ) assert print_obj(completion.choices[0], monkeypatch) == snapshot( """\ ParsedChoice( finish_reason='stop', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content='{"color":"red","hex_color_code":"#FF0000"}', function_call=None, parsed=ColorDetection(color=, hex_color_code='#FF0000'), refusal=None, role='assistant', tool_calls=None ) ) """ ) @pytest.mark.respx(base_url=base_url) def test_parse_pydantic_model_multiple_choices( client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch ) -> None: class Location(BaseModel): city: str temperature: float units: Literal["c", "f"] completion = make_snapshot_request( lambda c: c.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in SF?", }, ], n=3, response_format=Location, ), content_snapshot=snapshot( '{"id": "chatcmpl-ABfvp8qzboW92q8ONDF4DPHlI7ckC", "object": "chat.completion", "created": 1727346157, "model": "gpt-4o-2024-08-06", "choices": [{"index": 0, "message": {"role": "assistant", "content": "{\\"city\\":\\"San Francisco\\",\\"temperature\\":64,\\"units\\":\\"f\\"}", "refusal": null}, "logprobs": null, "finish_reason": "stop"}, {"index": 1, "message": {"role": "assistant", "content": "{\\"city\\":\\"San Francisco\\",\\"temperature\\":65,\\"units\\":\\"f\\"}", "refusal": null}, "logprobs": null, "finish_reason": "stop"}, {"index": 2, "message": {"role": "assistant", "content": "{\\"city\\":\\"San Francisco\\",\\"temperature\\":63.0,\\"units\\":\\"f\\"}", "refusal": null}, "logprobs": null, "finish_reason": "stop"}], "usage": {"prompt_tokens": 79, "completion_tokens": 44, "total_tokens": 123, "completion_tokens_details": {"reasoning_tokens": 0}}, "system_fingerprint": "fp_b40fb1c6fb"}' ), path="/chat/completions", mock_client=client, respx_mock=respx_mock, ) assert print_obj(completion.choices, monkeypatch) == snapshot( """\ [ ParsedChoice( finish_reason='stop', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content='{"city":"San Francisco","temperature":64,"units":"f"}', function_call=None, parsed=Location(city='San Francisco', temperature=64.0, units='f'), refusal=None, role='assistant', tool_calls=None ) ), ParsedChoice( finish_reason='stop', index=1, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content='{"city":"San Francisco","temperature":65,"units":"f"}', function_call=None, parsed=Location(city='San Francisco', temperature=65.0, units='f'), refusal=None, role='assistant', tool_calls=None ) ), ParsedChoice( finish_reason='stop', index=2, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content='{"city":"San Francisco","temperature":63.0,"units":"f"}', function_call=None, parsed=Location(city='San Francisco', temperature=63.0, units='f'), refusal=None, role='assistant', tool_calls=None ) ) ] """ ) @pytest.mark.respx(base_url=base_url) @pytest.mark.skipif(PYDANTIC_V1, reason="dataclasses only supported in v2") def test_parse_pydantic_dataclass(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: from pydantic.dataclasses import dataclass @dataclass class CalendarEvent: name: str date: str participants: List[str] completion = make_snapshot_request( lambda c: c.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[ {"role": "system", "content": "Extract the event information."}, {"role": "user", "content": "Alice and Bob are going to a science fair on Friday."}, ], response_format=CalendarEvent, ), content_snapshot=snapshot( '{"id": "chatcmpl-ABfvqhz4uUUWsw8Ohw2Mp9B4sKKV8", "object": "chat.completion", "created": 1727346158, "model": "gpt-4o-2024-08-06", "choices": [{"index": 0, "message": {"role": "assistant", "content": "{\\"name\\":\\"Science Fair\\",\\"date\\":\\"Friday\\",\\"participants\\":[\\"Alice\\",\\"Bob\\"]}", "refusal": null}, "logprobs": null, "finish_reason": "stop"}], "usage": {"prompt_tokens": 92, "completion_tokens": 17, "total_tokens": 109, "completion_tokens_details": {"reasoning_tokens": 0}}, "system_fingerprint": "fp_7568d46099"}' ), path="/chat/completions", mock_client=client, respx_mock=respx_mock, ) assert print_obj(completion, monkeypatch) == snapshot( """\ ParsedChatCompletion( choices=[ ParsedChoice( finish_reason='stop', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content='{"name":"Science Fair","date":"Friday","participants":["Alice","Bob"]}', function_call=None, parsed=CalendarEvent(name='Science Fair', date='Friday', participants=['Alice', 'Bob']), refusal=None, role='assistant', tool_calls=None ) ) ], created=1727346158, id='chatcmpl-ABfvqhz4uUUWsw8Ohw2Mp9B4sKKV8', model='gpt-4o-2024-08-06', object='chat.completion', service_tier=None, system_fingerprint='fp_7568d46099', usage=CompletionUsage( completion_tokens=17, completion_tokens_details=CompletionTokensDetails( accepted_prediction_tokens=None, audio_tokens=None, reasoning_tokens=0, rejected_prediction_tokens=None ), prompt_tokens=92, prompt_tokens_details=None, total_tokens=109 ) ) """ ) @pytest.mark.respx(base_url=base_url) def test_pydantic_tool_model_all_types(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: completion = make_snapshot_request( lambda c: c.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "look up all my orders in may of last year that were fulfilled but not delivered on time", }, ], tools=[openai.pydantic_function_tool(Query)], response_format=Query, ), content_snapshot=snapshot( '{"id": "chatcmpl-ABfvtNiaTNUF6OymZUnEFc9lPq9p1", "object": "chat.completion", "created": 1727346161, "model": "gpt-4o-2024-08-06", "choices": [{"index": 0, "message": {"role": "assistant", "content": null, "tool_calls": [{"id": "call_NKpApJybW1MzOjZO2FzwYw0d", "type": "function", "function": {"name": "Query", "arguments": "{\\"name\\":\\"May 2022 Fulfilled Orders Not Delivered on Time\\",\\"table_name\\":\\"orders\\",\\"columns\\":[\\"id\\",\\"status\\",\\"expected_delivery_date\\",\\"delivered_at\\",\\"shipped_at\\",\\"ordered_at\\",\\"canceled_at\\"],\\"conditions\\":[{\\"column\\":\\"ordered_at\\",\\"operator\\":\\">=\\",\\"value\\":\\"2022-05-01\\"},{\\"column\\":\\"ordered_at\\",\\"operator\\":\\"<=\\",\\"value\\":\\"2022-05-31\\"},{\\"column\\":\\"status\\",\\"operator\\":\\"=\\",\\"value\\":\\"fulfilled\\"},{\\"column\\":\\"delivered_at\\",\\"operator\\":\\">\\",\\"value\\":{\\"column_name\\":\\"expected_delivery_date\\"}}],\\"order_by\\":\\"asc\\"}"}}], "refusal": null}, "logprobs": null, "finish_reason": "tool_calls"}], "usage": {"prompt_tokens": 512, "completion_tokens": 132, "total_tokens": 644, "completion_tokens_details": {"reasoning_tokens": 0}}, "system_fingerprint": "fp_7568d46099"}' ), path="/chat/completions", mock_client=client, respx_mock=respx_mock, ) assert print_obj(completion.choices[0], monkeypatch) == snapshot( """\ ParsedChoice( finish_reason='tool_calls', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content=None, function_call=None, parsed=None, refusal=None, role='assistant', tool_calls=[ ParsedFunctionToolCall( function=ParsedFunction( arguments='{"name":"May 2022 Fulfilled Orders Not Delivered on Time","table_name":"orders","columns":["id","status","expected_delivery_date","delivered_at","shipped_at","ordered_at"," canceled_at"],"conditions":[{"column":"ordered_at","operator":">=","value":"2022-05-01"},{"column":"ordered_at","operato r":"<=","value":"2022-05-31"},{"column":"status","operator":"=","value":"fulfilled"},{"column":"delivered_at","operator" :">","value":{"column_name":"expected_delivery_date"}}],"order_by":"asc"}', name='Query', parsed_arguments=Query( columns=[ , , , , , , ], conditions=[ Condition(column='ordered_at', operator=='>, value='2022-05-01'), Condition(column='ordered_at', operator='>, value=DynamicValue(column_name='expected_delivery_date') ) ], name='May 2022 Fulfilled Orders Not Delivered on Time', order_by=, table_name= ) ), id='call_NKpApJybW1MzOjZO2FzwYw0d', type='function' ) ] ) ) """ ) @pytest.mark.respx(base_url=base_url) def test_parse_max_tokens_reached(client: OpenAI, respx_mock: MockRouter) -> None: class Location(BaseModel): city: str temperature: float units: Literal["c", "f"] with pytest.raises(openai.LengthFinishReasonError): make_snapshot_request( lambda c: c.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in SF?", }, ], max_tokens=1, response_format=Location, ), content_snapshot=snapshot( '{"id": "chatcmpl-ABfvvX7eB1KsfeZj8VcF3z7G7SbaA", "object": "chat.completion", "created": 1727346163, "model": "gpt-4o-2024-08-06", "choices": [{"index": 0, "message": {"role": "assistant", "content": "{\\"", "refusal": null}, "logprobs": null, "finish_reason": "length"}], "usage": {"prompt_tokens": 79, "completion_tokens": 1, "total_tokens": 80, "completion_tokens_details": {"reasoning_tokens": 0}}, "system_fingerprint": "fp_7568d46099"}' ), path="/chat/completions", mock_client=client, respx_mock=respx_mock, ) @pytest.mark.respx(base_url=base_url) def test_parse_pydantic_model_refusal(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: class Location(BaseModel): city: str temperature: float units: Literal["c", "f"] completion = make_snapshot_request( lambda c: c.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "How do I make anthrax?", }, ], response_format=Location, ), content_snapshot=snapshot( '{"id": "chatcmpl-ABfvwoKVWPQj2UPlAcAKM7s40GsRx", "object": "chat.completion", "created": 1727346164, "model": "gpt-4o-2024-08-06", "choices": [{"index": 0, "message": {"role": "assistant", "content": null, "refusal": "I\'m very sorry, but I can\'t assist with that."}, "logprobs": null, "finish_reason": "stop"}], "usage": {"prompt_tokens": 79, "completion_tokens": 12, "total_tokens": 91, "completion_tokens_details": {"reasoning_tokens": 0}}, "system_fingerprint": "fp_5050236cbd"}' ), path="/chat/completions", mock_client=client, respx_mock=respx_mock, ) assert print_obj(completion.choices, monkeypatch) == snapshot( """\ [ ParsedChoice( finish_reason='stop', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content=None, function_call=None, parsed=None, refusal="I'm very sorry, but I can't assist with that.", role='assistant', tool_calls=None ) ) ] """ ) @pytest.mark.respx(base_url=base_url) def test_parse_pydantic_tool(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: class GetWeatherArgs(BaseModel): city: str country: str units: Literal["c", "f"] = "c" completion = make_snapshot_request( lambda c: c.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in Edinburgh?", }, ], tools=[ openai.pydantic_function_tool(GetWeatherArgs), ], ), content_snapshot=snapshot( '{"id": "chatcmpl-ABfvx6Z4dchiW2nya1N8KMsHFrQRE", "object": "chat.completion", "created": 1727346165, "model": "gpt-4o-2024-08-06", "choices": [{"index": 0, "message": {"role": "assistant", "content": null, "tool_calls": [{"id": "call_Y6qJ7ofLgOrBnMD5WbVAeiRV", "type": "function", "function": {"name": "GetWeatherArgs", "arguments": "{\\"city\\":\\"Edinburgh\\",\\"country\\":\\"UK\\",\\"units\\":\\"c\\"}"}}], "refusal": null}, "logprobs": null, "finish_reason": "tool_calls"}], "usage": {"prompt_tokens": 76, "completion_tokens": 24, "total_tokens": 100, "completion_tokens_details": {"reasoning_tokens": 0}}, "system_fingerprint": "fp_e45dabd248"}' ), path="/chat/completions", mock_client=client, respx_mock=respx_mock, ) assert print_obj(completion.choices, monkeypatch) == snapshot( """\ [ ParsedChoice( finish_reason='tool_calls', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content=None, function_call=None, parsed=None, refusal=None, role='assistant', tool_calls=[ ParsedFunctionToolCall( function=ParsedFunction( arguments='{"city":"Edinburgh","country":"UK","units":"c"}', name='GetWeatherArgs', parsed_arguments=GetWeatherArgs(city='Edinburgh', country='UK', units='c') ), id='call_Y6qJ7ofLgOrBnMD5WbVAeiRV', type='function' ) ] ) ) ] """ ) @pytest.mark.respx(base_url=base_url) def test_parse_multiple_pydantic_tools(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: class GetWeatherArgs(BaseModel): """Get the temperature for the given country/city combo""" city: str country: str units: Literal["c", "f"] = "c" class GetStockPrice(BaseModel): ticker: str exchange: str completion = make_snapshot_request( lambda c: c.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in Edinburgh?", }, { "role": "user", "content": "What's the price of AAPL?", }, ], tools=[ openai.pydantic_function_tool(GetWeatherArgs), openai.pydantic_function_tool( GetStockPrice, name="get_stock_price", description="Fetch the latest price for a given ticker" ), ], ), content_snapshot=snapshot( '{"id": "chatcmpl-ABfvyvfNWKcl7Ohqos4UFrmMs1v4C", "object": "chat.completion", "created": 1727346166, "model": "gpt-4o-2024-08-06", "choices": [{"index": 0, "message": {"role": "assistant", "content": null, "tool_calls": [{"id": "call_fdNz3vOBKYgOIpMdWotB9MjY", "type": "function", "function": {"name": "GetWeatherArgs", "arguments": "{\\"city\\": \\"Edinburgh\\", \\"country\\": \\"GB\\", \\"units\\": \\"c\\"}"}}, {"id": "call_h1DWI1POMJLb0KwIyQHWXD4p", "type": "function", "function": {"name": "get_stock_price", "arguments": "{\\"ticker\\": \\"AAPL\\", \\"exchange\\": \\"NASDAQ\\"}"}}], "refusal": null}, "logprobs": null, "finish_reason": "tool_calls"}], "usage": {"prompt_tokens": 149, "completion_tokens": 60, "total_tokens": 209, "completion_tokens_details": {"reasoning_tokens": 0}}, "system_fingerprint": "fp_b40fb1c6fb"}' ), path="/chat/completions", mock_client=client, respx_mock=respx_mock, ) assert print_obj(completion.choices, monkeypatch) == snapshot( """\ [ ParsedChoice( finish_reason='tool_calls', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content=None, function_call=None, parsed=None, refusal=None, role='assistant', tool_calls=[ ParsedFunctionToolCall( function=ParsedFunction( arguments='{"city": "Edinburgh", "country": "GB", "units": "c"}', name='GetWeatherArgs', parsed_arguments=GetWeatherArgs(city='Edinburgh', country='GB', units='c') ), id='call_fdNz3vOBKYgOIpMdWotB9MjY', type='function' ), ParsedFunctionToolCall( function=ParsedFunction( arguments='{"ticker": "AAPL", "exchange": "NASDAQ"}', name='get_stock_price', parsed_arguments=GetStockPrice(exchange='NASDAQ', ticker='AAPL') ), id='call_h1DWI1POMJLb0KwIyQHWXD4p', type='function' ) ] ) ) ] """ ) @pytest.mark.respx(base_url=base_url) def test_parse_strict_tools(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: completion = make_snapshot_request( lambda c: c.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in SF?", }, ], tools=[ { "type": "function", "function": { "name": "get_weather", "parameters": { "type": "object", "properties": { "city": {"type": "string"}, "state": {"type": "string"}, }, "required": [ "city", "state", ], "additionalProperties": False, }, "strict": True, }, } ], ), content_snapshot=snapshot( '{"id": "chatcmpl-ABfvzdvCI6RaIkiEFNjqGXCSYnlzf", "object": "chat.completion", "created": 1727346167, "model": "gpt-4o-2024-08-06", "choices": [{"index": 0, "message": {"role": "assistant", "content": null, "tool_calls": [{"id": "call_CUdUoJpsWWVdxXntucvnol1M", "type": "function", "function": {"name": "get_weather", "arguments": "{\\"city\\":\\"San Francisco\\",\\"state\\":\\"CA\\"}"}}], "refusal": null}, "logprobs": null, "finish_reason": "tool_calls"}], "usage": {"prompt_tokens": 48, "completion_tokens": 19, "total_tokens": 67, "completion_tokens_details": {"reasoning_tokens": 0}}, "system_fingerprint": "fp_5050236cbd"}' ), path="/chat/completions", mock_client=client, respx_mock=respx_mock, ) assert print_obj(completion.choices, monkeypatch) == snapshot( """\ [ ParsedChoice( finish_reason='tool_calls', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content=None, function_call=None, parsed=None, refusal=None, role='assistant', tool_calls=[ ParsedFunctionToolCall( function=ParsedFunction( arguments='{"city":"San Francisco","state":"CA"}', name='get_weather', parsed_arguments={'city': 'San Francisco', 'state': 'CA'} ), id='call_CUdUoJpsWWVdxXntucvnol1M', type='function' ) ] ) ) ] """ ) def test_parse_non_strict_tools(client: OpenAI) -> None: with pytest.raises( ValueError, match="`get_weather` is not strict. Only `strict` function tools can be auto-parsed" ): client.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[], tools=[ { "type": "function", "function": { "name": "get_weather", "parameters": {}, }, } ], ) @pytest.mark.respx(base_url=base_url) def test_parse_pydantic_raw_response(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: class Location(BaseModel): city: str temperature: float units: Literal["c", "f"] response = make_snapshot_request( lambda c: c.chat.completions.with_raw_response.parse( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in SF?", }, ], response_format=Location, ), content_snapshot=snapshot( '{"id": "chatcmpl-ABrDYCa8W1w66eUxKDO8TQF1m6trT", "object": "chat.completion", "created": 1727389540, "model": "gpt-4o-2024-08-06", "choices": [{"index": 0, "message": {"role": "assistant", "content": "{\\"city\\":\\"San Francisco\\",\\"temperature\\":58,\\"units\\":\\"f\\"}", "refusal": null}, "logprobs": null, "finish_reason": "stop"}], "usage": {"prompt_tokens": 79, "completion_tokens": 14, "total_tokens": 93, "completion_tokens_details": {"reasoning_tokens": 0}}, "system_fingerprint": "fp_5050236cbd"}' ), path="/chat/completions", mock_client=client, respx_mock=respx_mock, ) assert response.http_request.headers.get("x-stainless-helper-method") == "chat.completions.parse" completion = response.parse() message = completion.choices[0].message assert message.parsed is not None assert isinstance(message.parsed.city, str) assert print_obj(completion, monkeypatch) == snapshot( """\ ParsedChatCompletion( choices=[ ParsedChoice( finish_reason='stop', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content='{"city":"San Francisco","temperature":58,"units":"f"}', function_call=None, parsed=Location(city='San Francisco', temperature=58.0, units='f'), refusal=None, role='assistant', tool_calls=None ) ) ], created=1727389540, id='chatcmpl-ABrDYCa8W1w66eUxKDO8TQF1m6trT', model='gpt-4o-2024-08-06', object='chat.completion', service_tier=None, system_fingerprint='fp_5050236cbd', usage=CompletionUsage( completion_tokens=14, completion_tokens_details=CompletionTokensDetails( accepted_prediction_tokens=None, audio_tokens=None, reasoning_tokens=0, rejected_prediction_tokens=None ), prompt_tokens=79, prompt_tokens_details=None, total_tokens=93 ) ) """ ) @pytest.mark.respx(base_url=base_url) @pytest.mark.asyncio async def test_async_parse_pydantic_raw_response( async_client: AsyncOpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch ) -> None: class Location(BaseModel): city: str temperature: float units: Literal["c", "f"] response = await make_async_snapshot_request( lambda c: c.chat.completions.with_raw_response.parse( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in SF?", }, ], response_format=Location, ), content_snapshot=snapshot( '{"id": "chatcmpl-ABrDQWOiw0PK5JOsxl1D9ooeQgznq", "object": "chat.completion", "created": 1727389532, "model": "gpt-4o-2024-08-06", "choices": [{"index": 0, "message": {"role": "assistant", "content": "{\\"city\\":\\"San Francisco\\",\\"temperature\\":65,\\"units\\":\\"f\\"}", "refusal": null}, "logprobs": null, "finish_reason": "stop"}], "usage": {"prompt_tokens": 79, "completion_tokens": 14, "total_tokens": 93, "completion_tokens_details": {"reasoning_tokens": 0}}, "system_fingerprint": "fp_5050236cbd"}' ), path="/chat/completions", mock_client=async_client, respx_mock=respx_mock, ) assert response.http_request.headers.get("x-stainless-helper-method") == "chat.completions.parse" completion = response.parse() message = completion.choices[0].message assert message.parsed is not None assert isinstance(message.parsed.city, str) assert print_obj(completion, monkeypatch) == snapshot( """\ ParsedChatCompletion( choices=[ ParsedChoice( finish_reason='stop', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content='{"city":"San Francisco","temperature":65,"units":"f"}', function_call=None, parsed=Location(city='San Francisco', temperature=65.0, units='f'), refusal=None, role='assistant', tool_calls=None ) ) ], created=1727389532, id='chatcmpl-ABrDQWOiw0PK5JOsxl1D9ooeQgznq', model='gpt-4o-2024-08-06', object='chat.completion', service_tier=None, system_fingerprint='fp_5050236cbd', usage=CompletionUsage( completion_tokens=14, completion_tokens_details=CompletionTokensDetails( accepted_prediction_tokens=None, audio_tokens=None, reasoning_tokens=0, rejected_prediction_tokens=None ), prompt_tokens=79, prompt_tokens_details=None, total_tokens=93 ) ) """ ) @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) def test_parse_method_in_sync(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: checking_client: OpenAI | AsyncOpenAI = client if sync else async_client assert_signatures_in_sync( checking_client.chat.completions.create, checking_client.chat.completions.parse, exclude_params={"response_format", "stream"}, ) ================================================ FILE: tests/lib/chat/test_completions_streaming.py ================================================ from __future__ import annotations import os from typing import Any, Generic, Callable, Iterator, cast, overload from typing_extensions import Literal, TypeVar import rich import httpx import pytest from respx import MockRouter from pydantic import BaseModel from inline_snapshot import ( external, snapshot, outsource, # pyright: ignore[reportUnknownVariableType] get_snapshot_value, ) import openai from openai import OpenAI, AsyncOpenAI from openai._utils import consume_sync_iterator, assert_signatures_in_sync from openai._compat import model_copy from openai.types.chat import ChatCompletionChunk from openai.lib.streaming.chat import ( ContentDoneEvent, ChatCompletionStream, ChatCompletionStreamEvent, ChatCompletionStreamState, ChatCompletionStreamManager, ParsedChatCompletionSnapshot, ) from openai.lib._parsing._completions import ResponseFormatT from ..utils import print_obj from ...conftest import base_url _T = TypeVar("_T") # all the snapshots in this file are auto-generated from the live API # # you can update them with # # `OPENAI_LIVE=1 pytest --inline-snapshot=fix -p no:xdist -o addopts=""` @pytest.mark.respx(base_url=base_url) def test_parse_nothing(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: listener = _make_stream_snapshot_request( lambda c: c.chat.completions.stream( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in SF?", }, ], ), content_snapshot=snapshot(external("e2aad469b71d*.bin")), mock_client=client, respx_mock=respx_mock, ) assert print_obj(listener.stream.get_final_completion().choices, monkeypatch) == snapshot( """\ [ ParsedChoice( finish_reason='stop', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content="I'm unable to provide real-time weather updates. To get the current weather in San Francisco, I recommend checking a reliable weather website or a weather app.", function_call=None, parsed=None, refusal=None, role='assistant', tool_calls=None ) ) ] """ ) assert print_obj(listener.get_event_by_type("content.done"), monkeypatch) == snapshot( """\ ContentDoneEvent( content="I'm unable to provide real-time weather updates. To get the current weather in San Francisco, I recommend checking a reliable weather website or a weather app.", parsed=None, type='content.done' ) """ ) @pytest.mark.respx(base_url=base_url) def test_parse_pydantic_model(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: class Location(BaseModel): city: str temperature: float units: Literal["c", "f"] done_snapshots: list[ParsedChatCompletionSnapshot] = [] def on_event(stream: ChatCompletionStream[Location], event: ChatCompletionStreamEvent[Location]) -> None: if event.type == "content.done": done_snapshots.append(model_copy(stream.current_completion_snapshot, deep=True)) listener = _make_stream_snapshot_request( lambda c: c.chat.completions.stream( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in SF?", }, ], response_format=Location, ), content_snapshot=snapshot(external("7e5ea4d12e7c*.bin")), mock_client=client, respx_mock=respx_mock, on_event=on_event, ) assert len(done_snapshots) == 1 assert isinstance(done_snapshots[0].choices[0].message.parsed, Location) for event in reversed(listener.events): if event.type == "content.delta": data = cast(Any, event.parsed) assert isinstance(data["city"], str), data assert isinstance(data["temperature"], (int, float)), data assert isinstance(data["units"], str), data break else: rich.print(listener.events) raise AssertionError("Did not find a `content.delta` event") assert print_obj(listener.stream.get_final_completion(), monkeypatch) == snapshot( """\ ParsedChatCompletion( choices=[ ParsedChoice( finish_reason='stop', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content='{"city":"San Francisco","temperature":61,"units":"f"}', function_call=None, parsed=Location(city='San Francisco', temperature=61.0, units='f'), refusal=None, role='assistant', tool_calls=None ) ) ], created=1727346169, id='chatcmpl-ABfw1e5abtU8OwGr15vOreYVb2MiF', model='gpt-4o-2024-08-06', object='chat.completion', service_tier=None, system_fingerprint='fp_5050236cbd', usage=CompletionUsage( completion_tokens=14, completion_tokens_details=CompletionTokensDetails( accepted_prediction_tokens=None, audio_tokens=None, reasoning_tokens=0, rejected_prediction_tokens=None ), prompt_tokens=79, prompt_tokens_details=None, total_tokens=93 ) ) """ ) assert print_obj(listener.get_event_by_type("content.done"), monkeypatch) == snapshot( """\ ContentDoneEvent( content='{"city":"San Francisco","temperature":61,"units":"f"}', parsed=Location(city='San Francisco', temperature=61.0, units='f'), type='content.done' ) """ ) @pytest.mark.respx(base_url=base_url) def test_parse_pydantic_model_multiple_choices( client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch ) -> None: class Location(BaseModel): city: str temperature: float units: Literal["c", "f"] listener = _make_stream_snapshot_request( lambda c: c.chat.completions.stream( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in SF?", }, ], n=3, response_format=Location, ), content_snapshot=snapshot(external("a491adda08c3*.bin")), mock_client=client, respx_mock=respx_mock, ) assert [e.type for e in listener.events] == snapshot( [ "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.delta", "chunk", "content.done", "chunk", "content.done", "chunk", "content.done", "chunk", ] ) assert print_obj(listener.stream.get_final_completion().choices, monkeypatch) == snapshot( """\ [ ParsedChoice( finish_reason='stop', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content='{"city":"San Francisco","temperature":65,"units":"f"}', function_call=None, parsed=Location(city='San Francisco', temperature=65.0, units='f'), refusal=None, role='assistant', tool_calls=None ) ), ParsedChoice( finish_reason='stop', index=1, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content='{"city":"San Francisco","temperature":61,"units":"f"}', function_call=None, parsed=Location(city='San Francisco', temperature=61.0, units='f'), refusal=None, role='assistant', tool_calls=None ) ), ParsedChoice( finish_reason='stop', index=2, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content='{"city":"San Francisco","temperature":59,"units":"f"}', function_call=None, parsed=Location(city='San Francisco', temperature=59.0, units='f'), refusal=None, role='assistant', tool_calls=None ) ) ] """ ) @pytest.mark.respx(base_url=base_url) def test_parse_max_tokens_reached(client: OpenAI, respx_mock: MockRouter) -> None: class Location(BaseModel): city: str temperature: float units: Literal["c", "f"] with pytest.raises(openai.LengthFinishReasonError): _make_stream_snapshot_request( lambda c: c.chat.completions.stream( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in SF?", }, ], max_tokens=1, response_format=Location, ), content_snapshot=snapshot(external("4cc50a6135d2*.bin")), mock_client=client, respx_mock=respx_mock, ) @pytest.mark.respx(base_url=base_url) def test_parse_pydantic_model_refusal(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: class Location(BaseModel): city: str temperature: float units: Literal["c", "f"] listener = _make_stream_snapshot_request( lambda c: c.chat.completions.stream( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "How do I make anthrax?", }, ], response_format=Location, ), content_snapshot=snapshot(external("173417d55340*.bin")), mock_client=client, respx_mock=respx_mock, ) assert print_obj(listener.get_event_by_type("refusal.done"), monkeypatch) == snapshot("""\ RefusalDoneEvent(refusal="I'm sorry, I can't assist with that request.", type='refusal.done') """) assert print_obj(listener.stream.get_final_completion().choices, monkeypatch) == snapshot( """\ [ ParsedChoice( finish_reason='stop', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content=None, function_call=None, parsed=None, refusal="I'm sorry, I can't assist with that request.", role='assistant', tool_calls=None ) ) ] """ ) @pytest.mark.respx(base_url=base_url) def test_content_logprobs_events(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: listener = _make_stream_snapshot_request( lambda c: c.chat.completions.stream( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "Say foo", }, ], logprobs=True, ), content_snapshot=snapshot(external("83b060bae42e*.bin")), mock_client=client, respx_mock=respx_mock, ) assert print_obj([e for e in listener.events if e.type.startswith("logprobs")], monkeypatch) == snapshot("""\ [ LogprobsContentDeltaEvent( content=[ ChatCompletionTokenLogprob(bytes=[70, 111, 111], logprob=-0.0025094282, token='Foo', top_logprobs=[]) ], snapshot=[ ChatCompletionTokenLogprob(bytes=[70, 111, 111], logprob=-0.0025094282, token='Foo', top_logprobs=[]) ], type='logprobs.content.delta' ), LogprobsContentDeltaEvent( content=[ChatCompletionTokenLogprob(bytes=[33], logprob=-0.26638845, token='!', top_logprobs=[])], snapshot=[ ChatCompletionTokenLogprob(bytes=[70, 111, 111], logprob=-0.0025094282, token='Foo', top_logprobs=[]), ChatCompletionTokenLogprob(bytes=[33], logprob=-0.26638845, token='!', top_logprobs=[]) ], type='logprobs.content.delta' ), LogprobsContentDoneEvent( content=[ ChatCompletionTokenLogprob(bytes=[70, 111, 111], logprob=-0.0025094282, token='Foo', top_logprobs=[]), ChatCompletionTokenLogprob(bytes=[33], logprob=-0.26638845, token='!', top_logprobs=[]) ], type='logprobs.content.done' ) ] """) assert print_obj(listener.stream.get_final_completion().choices, monkeypatch) == snapshot("""\ [ ParsedChoice( finish_reason='stop', index=0, logprobs=ChoiceLogprobs( content=[ ChatCompletionTokenLogprob(bytes=[70, 111, 111], logprob=-0.0025094282, token='Foo', top_logprobs=[]), ChatCompletionTokenLogprob(bytes=[33], logprob=-0.26638845, token='!', top_logprobs=[]) ], refusal=None ), message=ParsedChatCompletionMessage( annotations=None, audio=None, content='Foo!', function_call=None, parsed=None, refusal=None, role='assistant', tool_calls=None ) ) ] """) @pytest.mark.respx(base_url=base_url) def test_refusal_logprobs_events(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: class Location(BaseModel): city: str temperature: float units: Literal["c", "f"] listener = _make_stream_snapshot_request( lambda c: c.chat.completions.stream( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "How do I make anthrax?", }, ], logprobs=True, response_format=Location, ), content_snapshot=snapshot(external("569c877e6942*.bin")), mock_client=client, respx_mock=respx_mock, ) assert print_obj([e.type for e in listener.events if e.type.startswith("logprobs")], monkeypatch) == snapshot("""\ [ 'logprobs.refusal.delta', 'logprobs.refusal.delta', 'logprobs.refusal.delta', 'logprobs.refusal.delta', 'logprobs.refusal.delta', 'logprobs.refusal.delta', 'logprobs.refusal.delta', 'logprobs.refusal.delta', 'logprobs.refusal.delta', 'logprobs.refusal.delta', 'logprobs.refusal.delta', 'logprobs.refusal.done' ] """) assert print_obj(listener.stream.get_final_completion().choices, monkeypatch) == snapshot("""\ [ ParsedChoice( finish_reason='stop', index=0, logprobs=ChoiceLogprobs( content=None, refusal=[ ChatCompletionTokenLogprob(bytes=[73, 39, 109], logprob=-0.0012038043, token="I'm", top_logprobs=[]), ChatCompletionTokenLogprob( bytes=[32, 118, 101, 114, 121], logprob=-0.8438816, token=' very', top_logprobs=[] ), ChatCompletionTokenLogprob( bytes=[32, 115, 111, 114, 114, 121], logprob=-3.4121115e-06, token=' sorry', top_logprobs=[] ), ChatCompletionTokenLogprob(bytes=[44], logprob=-3.3809047e-05, token=',', top_logprobs=[]), ChatCompletionTokenLogprob( bytes=[32, 98, 117, 116], logprob=-0.038048144, token=' but', top_logprobs=[] ), ChatCompletionTokenLogprob(bytes=[32, 73], logprob=-0.0016109125, token=' I', top_logprobs=[]), ChatCompletionTokenLogprob( bytes=[32, 99, 97, 110, 39, 116], logprob=-0.0073532974, token=" can't", top_logprobs=[] ), ChatCompletionTokenLogprob( bytes=[32, 97, 115, 115, 105, 115, 116], logprob=-0.0020837625, token=' assist', top_logprobs=[] ), ChatCompletionTokenLogprob( bytes=[32, 119, 105, 116, 104], logprob=-0.00318354, token=' with', top_logprobs=[] ), ChatCompletionTokenLogprob( bytes=[32, 116, 104, 97, 116], logprob=-0.0017186158, token=' that', top_logprobs=[] ), ChatCompletionTokenLogprob(bytes=[46], logprob=-0.57687104, token='.', top_logprobs=[]) ] ), message=ParsedChatCompletionMessage( annotations=None, audio=None, content=None, function_call=None, parsed=None, refusal="I'm very sorry, but I can't assist with that.", role='assistant', tool_calls=None ) ) ] """) @pytest.mark.respx(base_url=base_url) def test_parse_pydantic_tool(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: class GetWeatherArgs(BaseModel): city: str country: str units: Literal["c", "f"] = "c" listener = _make_stream_snapshot_request( lambda c: c.chat.completions.stream( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in Edinburgh?", }, ], tools=[ openai.pydantic_function_tool(GetWeatherArgs), ], ), content_snapshot=snapshot(external("c6aa7e397b71*.bin")), mock_client=client, respx_mock=respx_mock, ) assert print_obj(listener.stream.current_completion_snapshot.choices, monkeypatch) == snapshot( """\ [ ParsedChoice( finish_reason='tool_calls', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content=None, function_call=None, parsed=None, refusal=None, role='assistant', tool_calls=[ ParsedFunctionToolCall( function=ParsedFunction( arguments='{"city":"Edinburgh","country":"UK","units":"c"}', name='GetWeatherArgs', parsed_arguments=GetWeatherArgs(city='Edinburgh', country='UK', units='c') ), id='call_c91SqDXlYFuETYv8mUHzz6pp', index=0, type='function' ) ] ) ) ] """ ) assert print_obj(listener.stream.get_final_completion().choices, monkeypatch) == snapshot( """\ [ ParsedChoice( finish_reason='tool_calls', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content=None, function_call=None, parsed=None, refusal=None, role='assistant', tool_calls=[ ParsedFunctionToolCall( function=ParsedFunction( arguments='{"city":"Edinburgh","country":"UK","units":"c"}', name='GetWeatherArgs', parsed_arguments=GetWeatherArgs(city='Edinburgh', country='UK', units='c') ), id='call_c91SqDXlYFuETYv8mUHzz6pp', index=0, type='function' ) ] ) ) ] """ ) @pytest.mark.respx(base_url=base_url) def test_parse_multiple_pydantic_tools(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: class GetWeatherArgs(BaseModel): """Get the temperature for the given country/city combo""" city: str country: str units: Literal["c", "f"] = "c" class GetStockPrice(BaseModel): ticker: str exchange: str listener = _make_stream_snapshot_request( lambda c: c.chat.completions.stream( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in Edinburgh?", }, { "role": "user", "content": "What's the price of AAPL?", }, ], tools=[ openai.pydantic_function_tool(GetWeatherArgs), openai.pydantic_function_tool( GetStockPrice, name="get_stock_price", description="Fetch the latest price for a given ticker" ), ], ), content_snapshot=snapshot(external("f82268f2fefd*.bin")), mock_client=client, respx_mock=respx_mock, ) assert print_obj(listener.stream.current_completion_snapshot.choices, monkeypatch) == snapshot( """\ [ ParsedChoice( finish_reason='tool_calls', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content=None, function_call=None, parsed=None, refusal=None, role='assistant', tool_calls=[ ParsedFunctionToolCall( function=ParsedFunction( arguments='{"city": "Edinburgh", "country": "GB", "units": "c"}', name='GetWeatherArgs', parsed_arguments=GetWeatherArgs(city='Edinburgh', country='GB', units='c') ), id='call_JMW1whyEaYG438VE1OIflxA2', index=0, type='function' ), ParsedFunctionToolCall( function=ParsedFunction( arguments='{"ticker": "AAPL", "exchange": "NASDAQ"}', name='get_stock_price', parsed_arguments=GetStockPrice(exchange='NASDAQ', ticker='AAPL') ), id='call_DNYTawLBoN8fj3KN6qU9N1Ou', index=1, type='function' ) ] ) ) ] """ ) completion = listener.stream.get_final_completion() assert print_obj(completion.choices[0].message.tool_calls, monkeypatch) == snapshot( """\ [ ParsedFunctionToolCall( function=ParsedFunction( arguments='{"city": "Edinburgh", "country": "GB", "units": "c"}', name='GetWeatherArgs', parsed_arguments=GetWeatherArgs(city='Edinburgh', country='GB', units='c') ), id='call_JMW1whyEaYG438VE1OIflxA2', index=0, type='function' ), ParsedFunctionToolCall( function=ParsedFunction( arguments='{"ticker": "AAPL", "exchange": "NASDAQ"}', name='get_stock_price', parsed_arguments=GetStockPrice(exchange='NASDAQ', ticker='AAPL') ), id='call_DNYTawLBoN8fj3KN6qU9N1Ou', index=1, type='function' ) ] """ ) @pytest.mark.respx(base_url=base_url) def test_parse_strict_tools(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: listener = _make_stream_snapshot_request( lambda c: c.chat.completions.stream( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in SF?", }, ], tools=[ { "type": "function", "function": { "name": "get_weather", "parameters": { "type": "object", "properties": { "city": {"type": "string"}, "state": {"type": "string"}, }, "required": [ "city", "state", ], "additionalProperties": False, }, "strict": True, }, } ], ), content_snapshot=snapshot(external("a247c49c5fcd*.bin")), mock_client=client, respx_mock=respx_mock, ) assert print_obj(listener.stream.current_completion_snapshot.choices, monkeypatch) == snapshot( """\ [ ParsedChoice( finish_reason='tool_calls', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content=None, function_call=None, parsed=None, refusal=None, role='assistant', tool_calls=[ ParsedFunctionToolCall( function=ParsedFunction( arguments='{"city":"San Francisco","state":"CA"}', name='get_weather', parsed_arguments={'city': 'San Francisco', 'state': 'CA'} ), id='call_CTf1nWJLqSeRgDqaCG27xZ74', index=0, type='function' ) ] ) ) ] """ ) @pytest.mark.respx(base_url=base_url) def test_non_pydantic_response_format(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: listener = _make_stream_snapshot_request( lambda c: c.chat.completions.stream( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in SF? Give me any JSON back", }, ], response_format={"type": "json_object"}, ), content_snapshot=snapshot(external("d61558011839*.bin")), mock_client=client, respx_mock=respx_mock, ) assert print_obj(listener.stream.get_final_completion().choices, monkeypatch) == snapshot( """\ [ ParsedChoice( finish_reason='stop', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content='\\n {\\n "location": "San Francisco, CA",\\n "weather": {\\n "temperature": "18°C",\\n "condition": "Partly Cloudy",\\n "humidity": "72%",\\n "windSpeed": "15 km/h",\\n "windDirection": "NW"\\n },\\n "forecast": [\\n {\\n "day": "Monday",\\n "high": "20°C",\\n "low": "14°C",\\n "condition": "Sunny"\\n },\\n {\\n "day": "Tuesday",\\n "high": "19°C",\\n "low": "15°C",\\n "condition": "Mostly Cloudy"\\n },\\n {\\n "day": "Wednesday",\\n "high": "18°C",\\n "low": "14°C",\\n "condition": "Cloudy"\\n }\\n ]\\n }\\n', function_call=None, parsed=None, refusal=None, role='assistant', tool_calls=None ) ) ] """ ) @pytest.mark.respx(base_url=base_url) def test_allows_non_strict_tools_but_no_parsing( client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch ) -> None: listener = _make_stream_snapshot_request( lambda c: c.chat.completions.stream( model="gpt-4o-2024-08-06", messages=[{"role": "user", "content": "what's the weather in NYC?"}], tools=[ { "type": "function", "function": { "name": "get_weather", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}}, }, } ], ), content_snapshot=snapshot(external("2018feb66ae1*.bin")), mock_client=client, respx_mock=respx_mock, ) assert print_obj(listener.get_event_by_type("tool_calls.function.arguments.done"), monkeypatch) == snapshot("""\ FunctionToolCallArgumentsDoneEvent( arguments='{"city":"New York City"}', index=0, name='get_weather', parsed_arguments=None, type='tool_calls.function.arguments.done' ) """) assert print_obj(listener.stream.get_final_completion().choices, monkeypatch) == snapshot( """\ [ ParsedChoice( finish_reason='tool_calls', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content=None, function_call=None, parsed=None, refusal=None, role='assistant', tool_calls=[ ParsedFunctionToolCall( function=ParsedFunction( arguments='{"city":"New York City"}', name='get_weather', parsed_arguments=None ), id='call_4XzlGBLtUe9dy3GVNV4jhq7h', index=0, type='function' ) ] ) ) ] """ ) @pytest.mark.respx(base_url=base_url) def test_chat_completion_state_helper(client: OpenAI, respx_mock: MockRouter, monkeypatch: pytest.MonkeyPatch) -> None: state = ChatCompletionStreamState() def streamer(client: OpenAI) -> Iterator[ChatCompletionChunk]: stream = client.chat.completions.create( model="gpt-4o-2024-08-06", messages=[ { "role": "user", "content": "What's the weather like in SF?", }, ], stream=True, ) for chunk in stream: state.handle_chunk(chunk) yield chunk _make_raw_stream_snapshot_request( streamer, content_snapshot=snapshot(external("e2aad469b71d*.bin")), mock_client=client, respx_mock=respx_mock, ) assert print_obj(state.get_final_completion().choices, monkeypatch) == snapshot( """\ [ ParsedChoice( finish_reason='stop', index=0, logprobs=None, message=ParsedChatCompletionMessage( annotations=None, audio=None, content="I'm unable to provide real-time weather updates. To get the current weather in San Francisco, I recommend checking a reliable weather website or a weather app.", function_call=None, parsed=None, refusal=None, role='assistant', tool_calls=None ) ) ] """ ) @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) def test_stream_method_in_sync(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: checking_client: OpenAI | AsyncOpenAI = client if sync else async_client assert_signatures_in_sync( checking_client.chat.completions.create, checking_client.chat.completions.stream, exclude_params={"response_format", "stream"}, ) class StreamListener(Generic[ResponseFormatT]): def __init__(self, stream: ChatCompletionStream[ResponseFormatT]) -> None: self.stream = stream self.events: list[ChatCompletionStreamEvent[ResponseFormatT]] = [] def __iter__(self) -> Iterator[ChatCompletionStreamEvent[ResponseFormatT]]: for event in self.stream: self.events.append(event) yield event @overload def get_event_by_type(self, event_type: Literal["content.done"]) -> ContentDoneEvent[ResponseFormatT] | None: ... @overload def get_event_by_type(self, event_type: str) -> ChatCompletionStreamEvent[ResponseFormatT] | None: ... def get_event_by_type(self, event_type: str) -> ChatCompletionStreamEvent[ResponseFormatT] | None: return next((e for e in self.events if e.type == event_type), None) def _make_stream_snapshot_request( func: Callable[[OpenAI], ChatCompletionStreamManager[ResponseFormatT]], *, content_snapshot: Any, respx_mock: MockRouter, mock_client: OpenAI, on_event: Callable[[ChatCompletionStream[ResponseFormatT], ChatCompletionStreamEvent[ResponseFormatT]], Any] | None = None, ) -> StreamListener[ResponseFormatT]: live = os.environ.get("OPENAI_LIVE") == "1" if live: def _on_response(response: httpx.Response) -> None: # update the content snapshot assert outsource(response.read()) == content_snapshot respx_mock.stop() client = OpenAI( http_client=httpx.Client( event_hooks={ "response": [_on_response], } ) ) else: respx_mock.post("/chat/completions").mock( return_value=httpx.Response( 200, content=get_snapshot_value(content_snapshot), headers={"content-type": "text/event-stream"}, ) ) client = mock_client with func(client) as stream: listener = StreamListener(stream) for event in listener: if on_event: on_event(stream, event) if live: client.close() return listener def _make_raw_stream_snapshot_request( func: Callable[[OpenAI], Iterator[ChatCompletionChunk]], *, content_snapshot: Any, respx_mock: MockRouter, mock_client: OpenAI, ) -> None: live = os.environ.get("OPENAI_LIVE") == "1" if live: def _on_response(response: httpx.Response) -> None: # update the content snapshot assert outsource(response.read()) == content_snapshot respx_mock.stop() client = OpenAI( http_client=httpx.Client( event_hooks={ "response": [_on_response], } ) ) else: respx_mock.post("/chat/completions").mock( return_value=httpx.Response( 200, content=get_snapshot_value(content_snapshot), headers={"content-type": "text/event-stream"}, ) ) client = mock_client stream = func(client) consume_sync_iterator(stream) if live: client.close() ================================================ FILE: tests/lib/responses/__init__.py ================================================ ================================================ FILE: tests/lib/responses/test_responses.py ================================================ from __future__ import annotations from typing_extensions import TypeVar import pytest from respx import MockRouter from inline_snapshot import snapshot from openai import OpenAI, AsyncOpenAI from openai._utils import assert_signatures_in_sync from ...conftest import base_url from ..snapshots import make_snapshot_request _T = TypeVar("_T") # all the snapshots in this file are auto-generated from the live API # # you can update them with # # `OPENAI_LIVE=1 pytest --inline-snapshot=fix -p no:xdist -o addopts=""` @pytest.mark.respx(base_url=base_url) def test_output_text(client: OpenAI, respx_mock: MockRouter) -> None: response = make_snapshot_request( lambda c: c.responses.create( model="gpt-4o-mini", input="What's the weather like in SF?", ), content_snapshot=snapshot( '{"id": "resp_689a0b2545288193953c892439b42e2800b2e36c65a1fd4b", "object": "response", "created_at": 1754925861, "status": "completed", "background": false, "error": null, "incomplete_details": null, "instructions": null, "max_output_tokens": null, "max_tool_calls": null, "model": "gpt-4o-mini-2024-07-18", "output": [{"id": "msg_689a0b2637b08193ac478e568f49e3f900b2e36c65a1fd4b", "type": "message", "status": "completed", "content": [{"type": "output_text", "annotations": [], "logprobs": [], "text": "I can\'t provide real-time updates, but you can easily check the current weather in San Francisco using a weather website or app. Typically, San Francisco has cool, foggy summers and mild winters, so it\'s good to be prepared for variable weather!"}], "role": "assistant"}], "parallel_tool_calls": true, "previous_response_id": null, "prompt_cache_key": null, "reasoning": {"effort": null, "summary": null}, "safety_identifier": null, "service_tier": "default", "store": true, "temperature": 1.0, "text": {"format": {"type": "text"}, "verbosity": "medium"}, "tool_choice": "auto", "tools": [], "top_logprobs": 0, "top_p": 1.0, "truncation": "disabled", "usage": {"input_tokens": 14, "input_tokens_details": {"cached_tokens": 0}, "output_tokens": 50, "output_tokens_details": {"reasoning_tokens": 0}, "total_tokens": 64}, "user": null, "metadata": {}}' ), path="/responses", mock_client=client, respx_mock=respx_mock, ) assert response.output_text == snapshot( "I can't provide real-time updates, but you can easily check the current weather in San Francisco using a weather website or app. Typically, San Francisco has cool, foggy summers and mild winters, so it's good to be prepared for variable weather!" ) @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) def test_stream_method_definition_in_sync(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: checking_client: OpenAI | AsyncOpenAI = client if sync else async_client assert_signatures_in_sync( checking_client.responses.create, checking_client.responses.stream, exclude_params={"stream", "tools"}, ) @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) def test_parse_method_definition_in_sync(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: checking_client: OpenAI | AsyncOpenAI = client if sync else async_client assert_signatures_in_sync( checking_client.responses.create, checking_client.responses.parse, exclude_params={"tools"}, ) ================================================ FILE: tests/lib/schema_types/query.py ================================================ from enum import Enum from typing import List, Union, Optional from pydantic import BaseModel class Table(str, Enum): orders = "orders" customers = "customers" products = "products" class Column(str, Enum): id = "id" status = "status" expected_delivery_date = "expected_delivery_date" delivered_at = "delivered_at" shipped_at = "shipped_at" ordered_at = "ordered_at" canceled_at = "canceled_at" class Operator(str, Enum): eq = "=" gt = ">" lt = "<" le = "<=" ge = ">=" ne = "!=" class OrderBy(str, Enum): asc = "asc" desc = "desc" class DynamicValue(BaseModel): column_name: str class Condition(BaseModel): column: str operator: Operator value: Union[str, int, DynamicValue] class Query(BaseModel): name: Optional[str] = None table_name: Table columns: List[Column] conditions: List[Condition] order_by: OrderBy ================================================ FILE: tests/lib/snapshots.py ================================================ from __future__ import annotations import os import json from typing import Any, Callable, Awaitable from typing_extensions import TypeVar import httpx from respx import MockRouter from inline_snapshot import get_snapshot_value from openai import OpenAI, AsyncOpenAI _T = TypeVar("_T") def make_snapshot_request( func: Callable[[OpenAI], _T], *, content_snapshot: Any, respx_mock: MockRouter, mock_client: OpenAI, path: str, ) -> _T: live = os.environ.get("OPENAI_LIVE") == "1" if live: def _on_response(response: httpx.Response) -> None: # update the content snapshot assert json.dumps(json.loads(response.read())) == content_snapshot respx_mock.stop() client = OpenAI( http_client=httpx.Client( event_hooks={ "response": [_on_response], } ) ) else: respx_mock.post(path).mock( return_value=httpx.Response( 200, content=get_snapshot_value(content_snapshot), headers={"content-type": "application/json"}, ) ) client = mock_client result = func(client) if live: client.close() return result async def make_async_snapshot_request( func: Callable[[AsyncOpenAI], Awaitable[_T]], *, content_snapshot: Any, respx_mock: MockRouter, mock_client: AsyncOpenAI, path: str, ) -> _T: live = os.environ.get("OPENAI_LIVE") == "1" if live: async def _on_response(response: httpx.Response) -> None: # update the content snapshot assert json.dumps(json.loads(await response.aread())) == content_snapshot respx_mock.stop() client = AsyncOpenAI( http_client=httpx.AsyncClient( event_hooks={ "response": [_on_response], } ) ) else: respx_mock.post(path).mock( return_value=httpx.Response( 200, content=get_snapshot_value(content_snapshot), headers={"content-type": "application/json"}, ) ) client = mock_client result = await func(client) if live: await client.close() return result ================================================ FILE: tests/lib/test_assistants.py ================================================ from __future__ import annotations import pytest from openai import OpenAI, AsyncOpenAI from openai._utils import assert_signatures_in_sync @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) def test_create_and_run_poll_method_definition_in_sync(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: checking_client: OpenAI | AsyncOpenAI = client if sync else async_client assert_signatures_in_sync( checking_client.beta.threads.create_and_run, # pyright: ignore[reportDeprecated] checking_client.beta.threads.create_and_run_poll, exclude_params={"stream"}, ) @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) def test_create_and_run_stream_method_definition_in_sync(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: checking_client: OpenAI | AsyncOpenAI = client if sync else async_client assert_signatures_in_sync( checking_client.beta.threads.create_and_run, # pyright: ignore[reportDeprecated] checking_client.beta.threads.create_and_run_stream, exclude_params={"stream"}, ) @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) def test_run_stream_method_definition_in_sync(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: checking_client: OpenAI | AsyncOpenAI = client if sync else async_client assert_signatures_in_sync( checking_client.beta.threads.runs.create, # pyright: ignore[reportDeprecated] checking_client.beta.threads.runs.stream, # pyright: ignore[reportDeprecated] exclude_params={"stream"}, ) @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) def test_create_and_poll_method_definition_in_sync(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: checking_client: OpenAI | AsyncOpenAI = client if sync else async_client assert_signatures_in_sync( checking_client.beta.threads.runs.create, # pyright: ignore[reportDeprecated] checking_client.beta.threads.runs.create_and_poll, # pyright: ignore[reportDeprecated] exclude_params={"stream"}, ) ================================================ FILE: tests/lib/test_audio.py ================================================ from __future__ import annotations import sys import inspect import typing_extensions from typing import get_args import pytest from openai import OpenAI, AsyncOpenAI from tests.utils import evaluate_forwardref from openai._utils import assert_signatures_in_sync from openai._compat import is_literal_type from openai._utils._typing import is_union_type from openai.types.audio_response_format import AudioResponseFormat @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) def test_translation_create_overloads_in_sync(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: checking_client: OpenAI | AsyncOpenAI = client if sync else async_client fn = checking_client.audio.translations.create overload_response_formats: set[str] = set() for i, overload in enumerate(typing_extensions.get_overloads(fn)): assert_signatures_in_sync( fn, overload, exclude_params={"response_format", "stream"}, description=f" for overload {i}", ) sig = inspect.signature(overload) typ = evaluate_forwardref( sig.parameters["response_format"].annotation, globalns=sys.modules[fn.__module__].__dict__, ) if is_union_type(typ): for arg in get_args(typ): if not is_literal_type(arg): continue overload_response_formats.update(get_args(arg)) elif is_literal_type(typ): overload_response_formats.update(get_args(typ)) # 'diarized_json' applies only to transcriptions, not translations. src_response_formats: set[str] = set(get_args(AudioResponseFormat)) - {"diarized_json"} diff = src_response_formats.difference(overload_response_formats) assert len(diff) == 0, f"some response format options don't have overloads" @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) def test_transcription_create_overloads_in_sync(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: checking_client: OpenAI | AsyncOpenAI = client if sync else async_client fn = checking_client.audio.transcriptions.create overload_response_formats: set[str] = set() for i, overload in enumerate(typing_extensions.get_overloads(fn)): sig = inspect.signature(overload) typ = evaluate_forwardref( sig.parameters["response_format"].annotation, globalns=sys.modules[fn.__module__].__dict__, ) exclude_params = {"response_format", "stream"} # known_speaker_names and known_speaker_references are only supported by diarized_json if not (is_literal_type(typ) and set(get_args(typ)) == {"diarized_json"}): exclude_params.update({"known_speaker_names", "known_speaker_references"}) # diarized_json does not support these parameters if is_literal_type(typ) and set(get_args(typ)) == {"diarized_json"}: exclude_params.update({"include", "prompt", "timestamp_granularities"}) assert_signatures_in_sync( fn, overload, exclude_params=exclude_params, description=f" for overload {i}", ) if is_union_type(typ): for arg in get_args(typ): if not is_literal_type(arg): continue overload_response_formats.update(get_args(arg)) elif is_literal_type(typ): overload_response_formats.update(get_args(typ)) src_response_formats: set[str] = set(get_args(AudioResponseFormat)) diff = src_response_formats.difference(overload_response_formats) assert len(diff) == 0, f"some response format options don't have overloads" ================================================ FILE: tests/lib/test_azure.py ================================================ from __future__ import annotations import logging from typing import Union, cast from typing_extensions import Literal, Protocol import httpx import pytest from respx import MockRouter from openai._utils import SensitiveHeadersFilter, is_dict from openai._models import FinalRequestOptions from openai.lib.azure import AzureOpenAI, AsyncAzureOpenAI Client = Union[AzureOpenAI, AsyncAzureOpenAI] sync_client = AzureOpenAI( api_version="2023-07-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", ) async_client = AsyncAzureOpenAI( api_version="2023-07-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", ) class MockRequestCall(Protocol): request: httpx.Request @pytest.mark.parametrize("client", [sync_client, async_client]) def test_implicit_deployment_path(client: Client) -> None: req = client._build_request( FinalRequestOptions.construct( method="post", url="/chat/completions", json_data={"model": "my-deployment-model"}, ) ) assert ( req.url == "https://example-resource.azure.openai.com/openai/deployments/my-deployment-model/chat/completions?api-version=2023-07-01" ) @pytest.mark.parametrize( "client,method", [ (sync_client, "copy"), (sync_client, "with_options"), (async_client, "copy"), (async_client, "with_options"), ], ) def test_client_copying(client: Client, method: Literal["copy", "with_options"]) -> None: if method == "copy": copied = client.copy() else: copied = client.with_options() assert copied._custom_query == {"api-version": "2023-07-01"} @pytest.mark.parametrize( "client", [sync_client, async_client], ) def test_client_copying_override_options(client: Client) -> None: copied = client.copy( api_version="2022-05-01", ) assert copied._custom_query == {"api-version": "2022-05-01"} @pytest.mark.respx() def test_client_token_provider_refresh_sync(respx_mock: MockRouter) -> None: respx_mock.post( "https://example-resource.azure.openai.com/openai/deployments/gpt-4/chat/completions?api-version=2024-02-01" ).mock( side_effect=[ httpx.Response(500, json={"error": "server error"}), httpx.Response(200, json={"foo": "bar"}), ] ) counter = 0 def token_provider() -> str: nonlocal counter counter += 1 if counter == 1: return "first" return "second" client = AzureOpenAI( api_version="2024-02-01", azure_ad_token_provider=token_provider, azure_endpoint="https://example-resource.azure.openai.com", ) client.chat.completions.create(messages=[], model="gpt-4") calls = cast("list[MockRequestCall]", respx_mock.calls) assert len(calls) == 2 assert calls[0].request.headers.get("Authorization") == "Bearer first" assert calls[1].request.headers.get("Authorization") == "Bearer second" @pytest.mark.asyncio @pytest.mark.respx() async def test_client_token_provider_refresh_async(respx_mock: MockRouter) -> None: respx_mock.post( "https://example-resource.azure.openai.com/openai/deployments/gpt-4/chat/completions?api-version=2024-02-01" ).mock( side_effect=[ httpx.Response(500, json={"error": "server error"}), httpx.Response(200, json={"foo": "bar"}), ] ) counter = 0 def token_provider() -> str: nonlocal counter counter += 1 if counter == 1: return "first" return "second" client = AsyncAzureOpenAI( api_version="2024-02-01", azure_ad_token_provider=token_provider, azure_endpoint="https://example-resource.azure.openai.com", ) await client.chat.completions.create(messages=[], model="gpt-4") calls = cast("list[MockRequestCall]", respx_mock.calls) assert len(calls) == 2 assert calls[0].request.headers.get("Authorization") == "Bearer first" assert calls[1].request.headers.get("Authorization") == "Bearer second" class TestAzureLogging: @pytest.fixture(autouse=True) def logger_with_filter(self) -> logging.Logger: logger = logging.getLogger("openai") logger.setLevel(logging.DEBUG) logger.addFilter(SensitiveHeadersFilter()) return logger @pytest.mark.respx() def test_azure_api_key_redacted(self, respx_mock: MockRouter, caplog: pytest.LogCaptureFixture) -> None: respx_mock.post( "https://example-resource.azure.openai.com/openai/deployments/gpt-4/chat/completions?api-version=2024-06-01" ).mock(return_value=httpx.Response(200, json={"model": "gpt-4"})) client = AzureOpenAI( api_version="2024-06-01", api_key="example_api_key", azure_endpoint="https://example-resource.azure.openai.com", ) with caplog.at_level(logging.DEBUG): client.chat.completions.create(messages=[], model="gpt-4") for record in caplog.records: if is_dict(record.args) and record.args.get("headers") and is_dict(record.args["headers"]): assert record.args["headers"]["api-key"] == "" @pytest.mark.respx() def test_azure_bearer_token_redacted(self, respx_mock: MockRouter, caplog: pytest.LogCaptureFixture) -> None: respx_mock.post( "https://example-resource.azure.openai.com/openai/deployments/gpt-4/chat/completions?api-version=2024-06-01" ).mock(return_value=httpx.Response(200, json={"model": "gpt-4"})) client = AzureOpenAI( api_version="2024-06-01", azure_ad_token="example_token", azure_endpoint="https://example-resource.azure.openai.com", ) with caplog.at_level(logging.DEBUG): client.chat.completions.create(messages=[], model="gpt-4") for record in caplog.records: if is_dict(record.args) and record.args.get("headers") and is_dict(record.args["headers"]): assert record.args["headers"]["Authorization"] == "" @pytest.mark.asyncio @pytest.mark.respx() async def test_azure_api_key_redacted_async(self, respx_mock: MockRouter, caplog: pytest.LogCaptureFixture) -> None: respx_mock.post( "https://example-resource.azure.openai.com/openai/deployments/gpt-4/chat/completions?api-version=2024-06-01" ).mock(return_value=httpx.Response(200, json={"model": "gpt-4"})) client = AsyncAzureOpenAI( api_version="2024-06-01", api_key="example_api_key", azure_endpoint="https://example-resource.azure.openai.com", ) with caplog.at_level(logging.DEBUG): await client.chat.completions.create(messages=[], model="gpt-4") for record in caplog.records: if is_dict(record.args) and record.args.get("headers") and is_dict(record.args["headers"]): assert record.args["headers"]["api-key"] == "" @pytest.mark.asyncio @pytest.mark.respx() async def test_azure_bearer_token_redacted_async( self, respx_mock: MockRouter, caplog: pytest.LogCaptureFixture ) -> None: respx_mock.post( "https://example-resource.azure.openai.com/openai/deployments/gpt-4/chat/completions?api-version=2024-06-01" ).mock(return_value=httpx.Response(200, json={"model": "gpt-4"})) client = AsyncAzureOpenAI( api_version="2024-06-01", azure_ad_token="example_token", azure_endpoint="https://example-resource.azure.openai.com", ) with caplog.at_level(logging.DEBUG): await client.chat.completions.create(messages=[], model="gpt-4") for record in caplog.records: if is_dict(record.args) and record.args.get("headers") and is_dict(record.args["headers"]): assert record.args["headers"]["Authorization"] == "" @pytest.mark.parametrize( "client,base_url,api,json_data,expected", [ # Deployment-based endpoints # AzureOpenAI: No deployment specified ( AzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", ), "https://example-resource.azure.openai.com/openai/", "/chat/completions", {"model": "deployment-body"}, "https://example-resource.azure.openai.com/openai/deployments/deployment-body/chat/completions?api-version=2024-02-01", ), # AzureOpenAI: Deployment specified ( AzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", azure_deployment="deployment-client", ), "https://example-resource.azure.openai.com/openai/deployments/deployment-client/", "/chat/completions", {"model": "deployment-body"}, "https://example-resource.azure.openai.com/openai/deployments/deployment-client/chat/completions?api-version=2024-02-01", ), # AzureOpenAI: "deployments" in the DNS name ( AzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://deployments.example-resource.azure.openai.com", ), "https://deployments.example-resource.azure.openai.com/openai/", "/chat/completions", {"model": "deployment-body"}, "https://deployments.example-resource.azure.openai.com/openai/deployments/deployment-body/chat/completions?api-version=2024-02-01", ), # AzureOpenAI: Deployment called deployments ( AzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", azure_deployment="deployments", ), "https://example-resource.azure.openai.com/openai/deployments/deployments/", "/chat/completions", {"model": "deployment-body"}, "https://example-resource.azure.openai.com/openai/deployments/deployments/chat/completions?api-version=2024-02-01", ), # AzureOpenAI: base_url and azure_deployment specified; ignored b/c not supported ( AzureOpenAI( # type: ignore api_version="2024-02-01", api_key="example API key", base_url="https://example.azure-api.net/PTU/", azure_deployment="deployment-client", ), "https://example.azure-api.net/PTU/", "/chat/completions", {"model": "deployment-body"}, "https://example.azure-api.net/PTU/deployments/deployment-body/chat/completions?api-version=2024-02-01", ), # AsyncAzureOpenAI: No deployment specified ( AsyncAzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", ), "https://example-resource.azure.openai.com/openai/", "/chat/completions", {"model": "deployment-body"}, "https://example-resource.azure.openai.com/openai/deployments/deployment-body/chat/completions?api-version=2024-02-01", ), # AsyncAzureOpenAI: Deployment specified ( AsyncAzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", azure_deployment="deployment-client", ), "https://example-resource.azure.openai.com/openai/deployments/deployment-client/", "/chat/completions", {"model": "deployment-body"}, "https://example-resource.azure.openai.com/openai/deployments/deployment-client/chat/completions?api-version=2024-02-01", ), # AsyncAzureOpenAI: "deployments" in the DNS name ( AsyncAzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://deployments.example-resource.azure.openai.com", ), "https://deployments.example-resource.azure.openai.com/openai/", "/chat/completions", {"model": "deployment-body"}, "https://deployments.example-resource.azure.openai.com/openai/deployments/deployment-body/chat/completions?api-version=2024-02-01", ), # AsyncAzureOpenAI: Deployment called deployments ( AsyncAzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", azure_deployment="deployments", ), "https://example-resource.azure.openai.com/openai/deployments/deployments/", "/chat/completions", {"model": "deployment-body"}, "https://example-resource.azure.openai.com/openai/deployments/deployments/chat/completions?api-version=2024-02-01", ), # AsyncAzureOpenAI: base_url and azure_deployment specified; azure_deployment ignored b/c not supported ( AsyncAzureOpenAI( # type: ignore api_version="2024-02-01", api_key="example API key", base_url="https://example.azure-api.net/PTU/", azure_deployment="deployment-client", ), "https://example.azure-api.net/PTU/", "/chat/completions", {"model": "deployment-body"}, "https://example.azure-api.net/PTU/deployments/deployment-body/chat/completions?api-version=2024-02-01", ), ], ) def test_prepare_url_deployment_endpoint( client: Client, base_url: str, api: str, json_data: dict[str, str], expected: str ) -> None: req = client._build_request( FinalRequestOptions.construct( method="post", url=api, json_data=json_data, ) ) assert req.url == expected assert client.base_url == base_url @pytest.mark.parametrize( "client,base_url,api,json_data,expected", [ # Non-deployment endpoints # AzureOpenAI: No deployment specified ( AzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", ), "https://example-resource.azure.openai.com/openai/", "/models", {}, "https://example-resource.azure.openai.com/openai/models?api-version=2024-02-01", ), # AzureOpenAI: No deployment specified ( AzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", ), "https://example-resource.azure.openai.com/openai/", "/assistants", {"model": "deployment-body"}, "https://example-resource.azure.openai.com/openai/assistants?api-version=2024-02-01", ), # AzureOpenAI: Deployment specified ( AzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", azure_deployment="deployment-client", ), "https://example-resource.azure.openai.com/openai/deployments/deployment-client/", "/models", {}, "https://example-resource.azure.openai.com/openai/models?api-version=2024-02-01", ), # AzureOpenAI: Deployment specified ( AzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", azure_deployment="deployment-client", ), "https://example-resource.azure.openai.com/openai/deployments/deployment-client/", "/assistants", {"model": "deployment-body"}, "https://example-resource.azure.openai.com/openai/assistants?api-version=2024-02-01", ), # AzureOpenAI: "deployments" in the DNS name ( AzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://deployments.example-resource.azure.openai.com", ), "https://deployments.example-resource.azure.openai.com/openai/", "/models", {}, "https://deployments.example-resource.azure.openai.com/openai/models?api-version=2024-02-01", ), # AzureOpenAI: Deployment called "deployments" ( AzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", azure_deployment="deployments", ), "https://example-resource.azure.openai.com/openai/deployments/deployments/", "/models", {}, "https://example-resource.azure.openai.com/openai/models?api-version=2024-02-01", ), # AzureOpenAI: base_url and azure_deployment specified; azure_deployment ignored b/c not supported ( AzureOpenAI( # type: ignore api_version="2024-02-01", api_key="example API key", base_url="https://example.azure-api.net/PTU/", azure_deployment="deployment-client", ), "https://example.azure-api.net/PTU/", "/models", {}, "https://example.azure-api.net/PTU/models?api-version=2024-02-01", ), # AsyncAzureOpenAI: No deployment specified ( AsyncAzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", ), "https://example-resource.azure.openai.com/openai/", "/models", {}, "https://example-resource.azure.openai.com/openai/models?api-version=2024-02-01", ), # AsyncAzureOpenAI: No deployment specified ( AsyncAzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", ), "https://example-resource.azure.openai.com/openai/", "/assistants", {"model": "deployment-body"}, "https://example-resource.azure.openai.com/openai/assistants?api-version=2024-02-01", ), # AsyncAzureOpenAI: Deployment specified ( AsyncAzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", azure_deployment="deployment-client", ), "https://example-resource.azure.openai.com/openai/deployments/deployment-client/", "/models", {}, "https://example-resource.azure.openai.com/openai/models?api-version=2024-02-01", ), # AsyncAzureOpenAI: Deployment specified ( AsyncAzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", azure_deployment="deployment-client", ), "https://example-resource.azure.openai.com/openai/deployments/deployment-client/", "/assistants", {"model": "deployment-body"}, "https://example-resource.azure.openai.com/openai/assistants?api-version=2024-02-01", ), # AsyncAzureOpenAI: "deployments" in the DNS name ( AsyncAzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://deployments.example-resource.azure.openai.com", ), "https://deployments.example-resource.azure.openai.com/openai/", "/models", {}, "https://deployments.example-resource.azure.openai.com/openai/models?api-version=2024-02-01", ), # AsyncAzureOpenAI: Deployment called "deployments" ( AsyncAzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", azure_deployment="deployments", ), "https://example-resource.azure.openai.com/openai/deployments/deployments/", "/models", {}, "https://example-resource.azure.openai.com/openai/models?api-version=2024-02-01", ), # AsyncAzureOpenAI: base_url and azure_deployment specified; azure_deployment ignored b/c not supported ( AsyncAzureOpenAI( # type: ignore api_version="2024-02-01", api_key="example API key", base_url="https://example.azure-api.net/PTU/", azure_deployment="deployment-client", ), "https://example.azure-api.net/PTU/", "/models", {}, "https://example.azure-api.net/PTU/models?api-version=2024-02-01", ), ], ) def test_prepare_url_nondeployment_endpoint( client: Client, base_url: str, api: str, json_data: dict[str, str], expected: str ) -> None: req = client._build_request( FinalRequestOptions.construct( method="post", url=api, json_data=json_data, ) ) assert req.url == expected assert client.base_url == base_url @pytest.mark.parametrize( "client,base_url,json_data,expected", [ # Realtime endpoint # AzureOpenAI: No deployment specified ( AzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", ), "https://example-resource.azure.openai.com/openai/", {"model": "deployment-body"}, "wss://example-resource.azure.openai.com/openai/realtime?api-version=2024-02-01&deployment=deployment-body", ), # AzureOpenAI: Deployment specified ( AzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", azure_deployment="deployment-client", ), "https://example-resource.azure.openai.com/openai/deployments/deployment-client/", {"model": "deployment-body"}, "wss://example-resource.azure.openai.com/openai/realtime?api-version=2024-02-01&deployment=deployment-client", ), # AzureOpenAI: "deployments" in the DNS name ( AzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://deployments.azure.openai.com", ), "https://deployments.azure.openai.com/openai/", {"model": "deployment-body"}, "wss://deployments.azure.openai.com/openai/realtime?api-version=2024-02-01&deployment=deployment-body", ), # AzureOpenAI: Deployment called "deployments" ( AzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", azure_deployment="deployments", ), "https://example-resource.azure.openai.com/openai/deployments/deployments/", {"model": "deployment-body"}, "wss://example-resource.azure.openai.com/openai/realtime?api-version=2024-02-01&deployment=deployments", ), # AzureOpenAI: base_url and azure_deployment specified; azure_deployment ignored b/c not supported ( AzureOpenAI( # type: ignore api_version="2024-02-01", api_key="example API key", base_url="https://example.azure-api.net/PTU/", azure_deployment="my-deployment", ), "https://example.azure-api.net/PTU/", {"model": "deployment-body"}, "wss://example.azure-api.net/PTU/realtime?api-version=2024-02-01&deployment=deployment-body", ), # AzureOpenAI: websocket_base_url specified ( AzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", websocket_base_url="wss://example-resource.azure.openai.com/base", ), "https://example-resource.azure.openai.com/openai/", {"model": "deployment-body"}, "wss://example-resource.azure.openai.com/base/realtime?api-version=2024-02-01&deployment=deployment-body", ), ], ) def test_prepare_url_realtime(client: AzureOpenAI, base_url: str, json_data: dict[str, str], expected: str) -> None: url, _ = client._configure_realtime(json_data["model"], {}) assert str(url) == expected assert client.base_url == base_url @pytest.mark.parametrize( "client,base_url,json_data,expected", [ # AsyncAzureOpenAI: No deployment specified ( AsyncAzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", ), "https://example-resource.azure.openai.com/openai/", {"model": "deployment-body"}, "wss://example-resource.azure.openai.com/openai/realtime?api-version=2024-02-01&deployment=deployment-body", ), # AsyncAzureOpenAI: Deployment specified ( AsyncAzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", azure_deployment="deployment-client", ), "https://example-resource.azure.openai.com/openai/deployments/deployment-client/", {"model": "deployment-body"}, "wss://example-resource.azure.openai.com/openai/realtime?api-version=2024-02-01&deployment=deployment-client", ), # AsyncAzureOpenAI: "deployments" in the DNS name ( AsyncAzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://deployments.azure.openai.com", ), "https://deployments.azure.openai.com/openai/", {"model": "deployment-body"}, "wss://deployments.azure.openai.com/openai/realtime?api-version=2024-02-01&deployment=deployment-body", ), # AsyncAzureOpenAI: Deployment called "deployments" ( AsyncAzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", azure_deployment="deployments", ), "https://example-resource.azure.openai.com/openai/deployments/deployments/", {"model": "deployment-body"}, "wss://example-resource.azure.openai.com/openai/realtime?api-version=2024-02-01&deployment=deployments", ), # AsyncAzureOpenAI: base_url and azure_deployment specified; azure_deployment ignored b/c not supported ( AsyncAzureOpenAI( # type: ignore api_version="2024-02-01", api_key="example API key", base_url="https://example.azure-api.net/PTU/", azure_deployment="deployment-client", ), "https://example.azure-api.net/PTU/", {"model": "deployment-body"}, "wss://example.azure-api.net/PTU/realtime?api-version=2024-02-01&deployment=deployment-body", ), # AsyncAzureOpenAI: websocket_base_url specified ( AsyncAzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", websocket_base_url="wss://example-resource.azure.openai.com/base", ), "https://example-resource.azure.openai.com/openai/", {"model": "deployment-body"}, "wss://example-resource.azure.openai.com/base/realtime?api-version=2024-02-01&deployment=deployment-body", ), ], ) async def test_prepare_url_realtime_async( client: AsyncAzureOpenAI, base_url: str, json_data: dict[str, str], expected: str ) -> None: url, _ = await client._configure_realtime(json_data["model"], {}) assert str(url) == expected assert client.base_url == base_url def test_client_sets_base_url(client: Client) -> None: client = AzureOpenAI( api_version="2024-02-01", api_key="example API key", azure_endpoint="https://example-resource.azure.openai.com", azure_deployment="my-deployment", ) assert client.base_url == "https://example-resource.azure.openai.com/openai/deployments/my-deployment/" # (not recommended) user sets base_url to target different deployment client.base_url = "https://example-resource.azure.openai.com/openai/deployments/different-deployment/" req = client._build_request( FinalRequestOptions.construct( method="post", url="/chat/completions", json_data={"model": "placeholder"}, ) ) assert ( req.url == "https://example-resource.azure.openai.com/openai/deployments/different-deployment/chat/completions?api-version=2024-02-01" ) req = client._build_request( FinalRequestOptions.construct( method="post", url="/models", json_data={}, ) ) assert req.url == "https://example-resource.azure.openai.com/openai/models?api-version=2024-02-01" # (not recommended) user sets base_url to remove deployment client.base_url = "https://example-resource.azure.openai.com/openai/" req = client._build_request( FinalRequestOptions.construct( method="post", url="/chat/completions", json_data={"model": "deployment"}, ) ) assert ( req.url == "https://example-resource.azure.openai.com/openai/deployments/deployment/chat/completions?api-version=2024-02-01" ) req = client._build_request( FinalRequestOptions.construct( method="post", url="/models", json_data={}, ) ) assert req.url == "https://example-resource.azure.openai.com/openai/models?api-version=2024-02-01" ================================================ FILE: tests/lib/test_old_api.py ================================================ import pytest import openai from openai.lib._old_api import APIRemovedInV1 def test_basic_attribute_access_works() -> None: for attr in dir(openai): getattr(openai, attr) def test_helpful_error_is_raised() -> None: with pytest.raises(APIRemovedInV1): openai.Completion.create() # type: ignore with pytest.raises(APIRemovedInV1): openai.ChatCompletion.create() # type: ignore ================================================ FILE: tests/lib/test_pydantic.py ================================================ from __future__ import annotations from enum import Enum from pydantic import Field, BaseModel from inline_snapshot import snapshot import openai from openai._compat import PYDANTIC_V1 from openai.lib._pydantic import to_strict_json_schema from .schema_types.query import Query def test_most_types() -> None: if not PYDANTIC_V1: assert openai.pydantic_function_tool(Query)["function"] == snapshot( { "name": "Query", "strict": True, "parameters": { "$defs": { "Column": { "enum": [ "id", "status", "expected_delivery_date", "delivered_at", "shipped_at", "ordered_at", "canceled_at", ], "title": "Column", "type": "string", }, "Condition": { "properties": { "column": {"title": "Column", "type": "string"}, "operator": {"$ref": "#/$defs/Operator"}, "value": { "anyOf": [ {"type": "string"}, {"type": "integer"}, {"$ref": "#/$defs/DynamicValue"}, ], "title": "Value", }, }, "required": ["column", "operator", "value"], "title": "Condition", "type": "object", "additionalProperties": False, }, "DynamicValue": { "properties": {"column_name": {"title": "Column Name", "type": "string"}}, "required": ["column_name"], "title": "DynamicValue", "type": "object", "additionalProperties": False, }, "Operator": {"enum": ["=", ">", "<", "<=", ">=", "!="], "title": "Operator", "type": "string"}, "OrderBy": {"enum": ["asc", "desc"], "title": "OrderBy", "type": "string"}, "Table": {"enum": ["orders", "customers", "products"], "title": "Table", "type": "string"}, }, "properties": { "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "table_name": {"$ref": "#/$defs/Table"}, "columns": { "items": {"$ref": "#/$defs/Column"}, "title": "Columns", "type": "array", }, "conditions": { "items": {"$ref": "#/$defs/Condition"}, "title": "Conditions", "type": "array", }, "order_by": {"$ref": "#/$defs/OrderBy"}, }, "required": ["name", "table_name", "columns", "conditions", "order_by"], "title": "Query", "type": "object", "additionalProperties": False, }, } ) else: assert openai.pydantic_function_tool(Query)["function"] == snapshot( { "name": "Query", "strict": True, "parameters": { "title": "Query", "type": "object", "properties": { "name": {"title": "Name", "type": "string"}, "table_name": {"$ref": "#/definitions/Table"}, "columns": {"type": "array", "items": {"$ref": "#/definitions/Column"}}, "conditions": { "title": "Conditions", "type": "array", "items": {"$ref": "#/definitions/Condition"}, }, "order_by": {"$ref": "#/definitions/OrderBy"}, }, "required": ["name", "table_name", "columns", "conditions", "order_by"], "definitions": { "Table": { "title": "Table", "description": "An enumeration.", "enum": ["orders", "customers", "products"], "type": "string", }, "Column": { "title": "Column", "description": "An enumeration.", "enum": [ "id", "status", "expected_delivery_date", "delivered_at", "shipped_at", "ordered_at", "canceled_at", ], "type": "string", }, "Operator": { "title": "Operator", "description": "An enumeration.", "enum": ["=", ">", "<", "<=", ">=", "!="], "type": "string", }, "DynamicValue": { "title": "DynamicValue", "type": "object", "properties": {"column_name": {"title": "Column Name", "type": "string"}}, "required": ["column_name"], "additionalProperties": False, }, "Condition": { "title": "Condition", "type": "object", "properties": { "column": {"title": "Column", "type": "string"}, "operator": {"$ref": "#/definitions/Operator"}, "value": { "title": "Value", "anyOf": [ {"type": "string"}, {"type": "integer"}, {"$ref": "#/definitions/DynamicValue"}, ], }, }, "required": ["column", "operator", "value"], "additionalProperties": False, }, "OrderBy": { "title": "OrderBy", "description": "An enumeration.", "enum": ["asc", "desc"], "type": "string", }, }, "additionalProperties": False, }, } ) class Color(Enum): RED = "red" BLUE = "blue" GREEN = "green" class ColorDetection(BaseModel): color: Color = Field(description="The detected color") hex_color_code: str = Field(description="The hex color code of the detected color") def test_enums() -> None: if not PYDANTIC_V1: assert openai.pydantic_function_tool(ColorDetection)["function"] == snapshot( { "name": "ColorDetection", "strict": True, "parameters": { "$defs": {"Color": {"enum": ["red", "blue", "green"], "title": "Color", "type": "string"}}, "properties": { "color": { "description": "The detected color", "enum": ["red", "blue", "green"], "title": "Color", "type": "string", }, "hex_color_code": { "description": "The hex color code of the detected color", "title": "Hex Color Code", "type": "string", }, }, "required": ["color", "hex_color_code"], "title": "ColorDetection", "type": "object", "additionalProperties": False, }, } ) else: assert openai.pydantic_function_tool(ColorDetection)["function"] == snapshot( { "name": "ColorDetection", "strict": True, "parameters": { "properties": { "color": { "description": "The detected color", "title": "Color", "enum": ["red", "blue", "green"], }, "hex_color_code": { "description": "The hex color code of the detected color", "title": "Hex Color Code", "type": "string", }, }, "required": ["color", "hex_color_code"], "title": "ColorDetection", "definitions": { "Color": {"title": "Color", "description": "An enumeration.", "enum": ["red", "blue", "green"]} }, "type": "object", "additionalProperties": False, }, } ) class Star(BaseModel): name: str = Field(description="The name of the star.") class Galaxy(BaseModel): name: str = Field(description="The name of the galaxy.") largest_star: Star = Field(description="The largest star in the galaxy.") class Universe(BaseModel): name: str = Field(description="The name of the universe.") galaxy: Galaxy = Field(description="A galaxy in the universe.") def test_nested_inline_ref_expansion() -> None: if not PYDANTIC_V1: assert to_strict_json_schema(Universe) == snapshot( { "title": "Universe", "type": "object", "$defs": { "Star": { "title": "Star", "type": "object", "properties": { "name": { "type": "string", "title": "Name", "description": "The name of the star.", } }, "required": ["name"], "additionalProperties": False, }, "Galaxy": { "title": "Galaxy", "type": "object", "properties": { "name": { "type": "string", "title": "Name", "description": "The name of the galaxy.", }, "largest_star": { "title": "Star", "type": "object", "properties": { "name": { "type": "string", "title": "Name", "description": "The name of the star.", } }, "required": ["name"], "description": "The largest star in the galaxy.", "additionalProperties": False, }, }, "required": ["name", "largest_star"], "additionalProperties": False, }, }, "properties": { "name": { "type": "string", "title": "Name", "description": "The name of the universe.", }, "galaxy": { "title": "Galaxy", "type": "object", "properties": { "name": { "type": "string", "title": "Name", "description": "The name of the galaxy.", }, "largest_star": { "title": "Star", "type": "object", "properties": { "name": { "type": "string", "title": "Name", "description": "The name of the star.", } }, "required": ["name"], "description": "The largest star in the galaxy.", "additionalProperties": False, }, }, "required": ["name", "largest_star"], "description": "A galaxy in the universe.", "additionalProperties": False, }, }, "required": ["name", "galaxy"], "additionalProperties": False, } ) else: assert to_strict_json_schema(Universe) == snapshot( { "title": "Universe", "type": "object", "definitions": { "Star": { "title": "Star", "type": "object", "properties": { "name": {"title": "Name", "description": "The name of the star.", "type": "string"} }, "required": ["name"], "additionalProperties": False, }, "Galaxy": { "title": "Galaxy", "type": "object", "properties": { "name": {"title": "Name", "description": "The name of the galaxy.", "type": "string"}, "largest_star": { "title": "Largest Star", "description": "The largest star in the galaxy.", "type": "object", "properties": { "name": {"title": "Name", "description": "The name of the star.", "type": "string"} }, "required": ["name"], "additionalProperties": False, }, }, "required": ["name", "largest_star"], "additionalProperties": False, }, }, "properties": { "name": { "title": "Name", "description": "The name of the universe.", "type": "string", }, "galaxy": { "title": "Galaxy", "description": "A galaxy in the universe.", "type": "object", "properties": { "name": { "title": "Name", "description": "The name of the galaxy.", "type": "string", }, "largest_star": { "title": "Largest Star", "description": "The largest star in the galaxy.", "type": "object", "properties": { "name": {"title": "Name", "description": "The name of the star.", "type": "string"} }, "required": ["name"], "additionalProperties": False, }, }, "required": ["name", "largest_star"], "additionalProperties": False, }, }, "required": ["name", "galaxy"], "additionalProperties": False, } ) ================================================ FILE: tests/lib/utils.py ================================================ from __future__ import annotations import re from typing import Any, Iterable from typing_extensions import TypeAlias import pytest import pydantic from ..utils import rich_print_str ReprArgs: TypeAlias = "Iterable[tuple[str | None, Any]]" def print_obj(obj: object, monkeypatch: pytest.MonkeyPatch) -> str: """Pretty print an object to a string""" # monkeypatch pydantic model printing so that model fields # are always printed in the same order so we can reliably # use this for snapshot tests original_repr = pydantic.BaseModel.__repr_args__ def __repr_args__(self: pydantic.BaseModel) -> ReprArgs: return sorted(original_repr(self), key=lambda arg: arg[0] or arg) with monkeypatch.context() as m: m.setattr(pydantic.BaseModel, "__repr_args__", __repr_args__) string = rich_print_str(obj) # Pydantic v1 and v2 have different implementations of __repr__ and print out # generics differently, so we strip out generic type parameters to ensure # consistent snapshot tests across both versions return re.sub(r"([A-Za-z_]\w*)\[[^\[\]]+\](?=\()", r"\1", string) ================================================ FILE: tests/sample_file.txt ================================================ Hello, world! ================================================ FILE: tests/test_client.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import gc import os import sys import json import asyncio import inspect import dataclasses import tracemalloc from typing import Any, Union, TypeVar, Callable, Iterable, Iterator, Optional, Protocol, Coroutine, cast from unittest import mock from typing_extensions import Literal, AsyncIterator, override import httpx import pytest from respx import MockRouter from pydantic import ValidationError from openai import OpenAI, AsyncOpenAI, APIResponseValidationError from openai._types import Omit from openai._utils import asyncify from openai._models import BaseModel, FinalRequestOptions from openai._streaming import Stream, AsyncStream from openai._exceptions import OpenAIError, APIStatusError, APITimeoutError, APIResponseValidationError from openai._base_client import ( DEFAULT_TIMEOUT, HTTPX_DEFAULT_TIMEOUT, BaseClient, OtherPlatform, DefaultHttpxClient, DefaultAsyncHttpxClient, get_platform, make_request_options, ) from .utils import update_env T = TypeVar("T") base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") api_key = "My API Key" class MockRequestCall(Protocol): request: httpx.Request def _get_params(client: BaseClient[Any, Any]) -> dict[str, str]: request = client._build_request(FinalRequestOptions(method="get", url="/foo")) url = httpx.URL(request.url) return dict(url.params) def _low_retry_timeout(*_args: Any, **_kwargs: Any) -> float: return 0.1 def mirror_request_content(request: httpx.Request) -> httpx.Response: return httpx.Response(200, content=request.content) # note: we can't use the httpx.MockTransport class as it consumes the request # body itself, which means we can't test that the body is read lazily class MockTransport(httpx.BaseTransport, httpx.AsyncBaseTransport): def __init__( self, handler: Callable[[httpx.Request], httpx.Response] | Callable[[httpx.Request], Coroutine[Any, Any, httpx.Response]], ) -> None: self.handler = handler @override def handle_request( self, request: httpx.Request, ) -> httpx.Response: assert not inspect.iscoroutinefunction(self.handler), "handler must not be a coroutine function" assert inspect.isfunction(self.handler), "handler must be a function" return self.handler(request) @override async def handle_async_request( self, request: httpx.Request, ) -> httpx.Response: assert inspect.iscoroutinefunction(self.handler), "handler must be a coroutine function" return await self.handler(request) @dataclasses.dataclass class Counter: value: int = 0 def _make_sync_iterator(iterable: Iterable[T], counter: Optional[Counter] = None) -> Iterator[T]: for item in iterable: if counter: counter.value += 1 yield item async def _make_async_iterator(iterable: Iterable[T], counter: Optional[Counter] = None) -> AsyncIterator[T]: for item in iterable: if counter: counter.value += 1 yield item def _get_open_connections(client: OpenAI | AsyncOpenAI) -> int: transport = client._client._transport assert isinstance(transport, httpx.HTTPTransport) or isinstance(transport, httpx.AsyncHTTPTransport) pool = transport._pool return len(pool._requests) class TestOpenAI: @pytest.mark.respx(base_url=base_url) def test_raw_response(self, respx_mock: MockRouter, client: OpenAI) -> None: respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) assert response.json() == {"foo": "bar"} @pytest.mark.respx(base_url=base_url) def test_raw_response_for_binary(self, respx_mock: MockRouter, client: OpenAI) -> None: respx_mock.post("/foo").mock( return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') ) response = client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) assert response.json() == {"foo": "bar"} def test_copy(self, client: OpenAI) -> None: copied = client.copy() assert id(copied) != id(client) copied = client.copy(api_key="another My API Key") assert copied.api_key == "another My API Key" assert client.api_key == "My API Key" def test_copy_default_options(self, client: OpenAI) -> None: # options that have a default are overridden correctly copied = client.copy(max_retries=7) assert copied.max_retries == 7 assert client.max_retries == 2 copied2 = copied.copy(max_retries=6) assert copied2.max_retries == 6 assert copied.max_retries == 7 # timeout assert isinstance(client.timeout, httpx.Timeout) copied = client.copy(timeout=None) assert copied.timeout is None assert isinstance(client.timeout, httpx.Timeout) def test_copy_default_headers(self) -> None: client = OpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} ) assert client.default_headers["X-Foo"] == "bar" # does not override the already given value when not specified copied = client.copy() assert copied.default_headers["X-Foo"] == "bar" # merges already given headers copied = client.copy(default_headers={"X-Bar": "stainless"}) assert copied.default_headers["X-Foo"] == "bar" assert copied.default_headers["X-Bar"] == "stainless" # uses new values for any already given headers copied = client.copy(default_headers={"X-Foo": "stainless"}) assert copied.default_headers["X-Foo"] == "stainless" # set_default_headers # completely overrides already set values copied = client.copy(set_default_headers={}) assert copied.default_headers.get("X-Foo") is None copied = client.copy(set_default_headers={"X-Bar": "Robert"}) assert copied.default_headers["X-Bar"] == "Robert" with pytest.raises( ValueError, match="`default_headers` and `set_default_headers` arguments are mutually exclusive", ): client.copy(set_default_headers={}, default_headers={"X-Foo": "Bar"}) client.close() def test_copy_default_query(self) -> None: client = OpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"foo": "bar"} ) assert _get_params(client)["foo"] == "bar" # does not override the already given value when not specified copied = client.copy() assert _get_params(copied)["foo"] == "bar" # merges already given params copied = client.copy(default_query={"bar": "stainless"}) params = _get_params(copied) assert params["foo"] == "bar" assert params["bar"] == "stainless" # uses new values for any already given headers copied = client.copy(default_query={"foo": "stainless"}) assert _get_params(copied)["foo"] == "stainless" # set_default_query # completely overrides already set values copied = client.copy(set_default_query={}) assert _get_params(copied) == {} copied = client.copy(set_default_query={"bar": "Robert"}) assert _get_params(copied)["bar"] == "Robert" with pytest.raises( ValueError, # TODO: update match="`default_query` and `set_default_query` arguments are mutually exclusive", ): client.copy(set_default_query={}, default_query={"foo": "Bar"}) client.close() def test_copy_signature(self, client: OpenAI) -> None: # ensure the same parameters that can be passed to the client are defined in the `.copy()` method init_signature = inspect.signature( # mypy doesn't like that we access the `__init__` property. client.__init__, # type: ignore[misc] ) copy_signature = inspect.signature(client.copy) exclude_params = {"transport", "proxies", "_strict_response_validation"} for name in init_signature.parameters.keys(): if name in exclude_params: continue copy_param = copy_signature.parameters.get(name) assert copy_param is not None, f"copy() signature is missing the {name} param" @pytest.mark.skipif(sys.version_info >= (3, 10), reason="fails because of a memory leak that started from 3.12") def test_copy_build_request(self, client: OpenAI) -> None: options = FinalRequestOptions(method="get", url="/foo") def build_request(options: FinalRequestOptions) -> None: client_copy = client.copy() client_copy._build_request(options) # ensure that the machinery is warmed up before tracing starts. build_request(options) gc.collect() tracemalloc.start(1000) snapshot_before = tracemalloc.take_snapshot() ITERATIONS = 10 for _ in range(ITERATIONS): build_request(options) gc.collect() snapshot_after = tracemalloc.take_snapshot() tracemalloc.stop() def add_leak(leaks: list[tracemalloc.StatisticDiff], diff: tracemalloc.StatisticDiff) -> None: if diff.count == 0: # Avoid false positives by considering only leaks (i.e. allocations that persist). return if diff.count % ITERATIONS != 0: # Avoid false positives by considering only leaks that appear per iteration. return for frame in diff.traceback: if any( frame.filename.endswith(fragment) for fragment in [ # to_raw_response_wrapper leaks through the @functools.wraps() decorator. # # removing the decorator fixes the leak for reasons we don't understand. "openai/_legacy_response.py", "openai/_response.py", # pydantic.BaseModel.model_dump || pydantic.BaseModel.dict leak memory for some reason. "openai/_compat.py", # Standard library leaks we don't care about. "/logging/__init__.py", ] ): return leaks.append(diff) leaks: list[tracemalloc.StatisticDiff] = [] for diff in snapshot_after.compare_to(snapshot_before, "traceback"): add_leak(leaks, diff) if leaks: for leak in leaks: print("MEMORY LEAK:", leak) for frame in leak.traceback: print(frame) raise AssertionError() def test_request_timeout(self, client: OpenAI) -> None: request = client._build_request(FinalRequestOptions(method="get", url="/foo")) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT request = client._build_request(FinalRequestOptions(method="get", url="/foo", timeout=httpx.Timeout(100.0))) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(100.0) def test_client_timeout_option(self) -> None: client = OpenAI(base_url=base_url, api_key=api_key, _strict_response_validation=True, timeout=httpx.Timeout(0)) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(0) client.close() def test_http_client_timeout_option(self) -> None: # custom timeout given to the httpx client should be used with httpx.Client(timeout=None) as http_client: client = OpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(None) client.close() # no timeout given to the httpx client should not use the httpx default with httpx.Client() as http_client: client = OpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT client.close() # explicitly passing the default timeout currently results in it being ignored with httpx.Client(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: client = OpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT # our default client.close() async def test_invalid_http_client(self) -> None: with pytest.raises(TypeError, match="Invalid `http_client` arg"): async with httpx.AsyncClient() as http_client: OpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=cast(Any, http_client), ) def test_default_headers_option(self) -> None: test_client = OpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} ) request = test_client._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "bar" assert request.headers.get("x-stainless-lang") == "python" test_client2 = OpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={ "X-Foo": "stainless", "X-Stainless-Lang": "my-overriding-header", }, ) request = test_client2._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "stainless" assert request.headers.get("x-stainless-lang") == "my-overriding-header" test_client.close() test_client2.close() def test_validate_headers(self) -> None: client = OpenAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) options = client._prepare_options(FinalRequestOptions(method="get", url="/foo")) request = client._build_request(options) assert request.headers.get("Authorization") == f"Bearer {api_key}" with pytest.raises(OpenAIError): with update_env(**{"OPENAI_API_KEY": Omit()}): client2 = OpenAI(base_url=base_url, api_key=None, _strict_response_validation=True) _ = client2 def test_default_query_option(self) -> None: client = OpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"query_param": "bar"} ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) url = httpx.URL(request.url) assert dict(url.params) == {"query_param": "bar"} request = client._build_request( FinalRequestOptions( method="get", url="/foo", params={"foo": "baz", "query_param": "overridden"}, ) ) url = httpx.URL(request.url) assert dict(url.params) == {"foo": "baz", "query_param": "overridden"} client.close() def test_request_extra_json(self, client: OpenAI) -> None: request = client._build_request( FinalRequestOptions( method="post", url="/foo", json_data={"foo": "bar"}, extra_json={"baz": False}, ), ) data = json.loads(request.content.decode("utf-8")) assert data == {"foo": "bar", "baz": False} request = client._build_request( FinalRequestOptions( method="post", url="/foo", extra_json={"baz": False}, ), ) data = json.loads(request.content.decode("utf-8")) assert data == {"baz": False} # `extra_json` takes priority over `json_data` when keys clash request = client._build_request( FinalRequestOptions( method="post", url="/foo", json_data={"foo": "bar", "baz": True}, extra_json={"baz": None}, ), ) data = json.loads(request.content.decode("utf-8")) assert data == {"foo": "bar", "baz": None} def test_request_extra_headers(self, client: OpenAI) -> None: request = client._build_request( FinalRequestOptions( method="post", url="/foo", **make_request_options(extra_headers={"X-Foo": "Foo"}), ), ) assert request.headers.get("X-Foo") == "Foo" # `extra_headers` takes priority over `default_headers` when keys clash request = client.with_options(default_headers={"X-Bar": "true"})._build_request( FinalRequestOptions( method="post", url="/foo", **make_request_options( extra_headers={"X-Bar": "false"}, ), ), ) assert request.headers.get("X-Bar") == "false" def test_request_extra_query(self, client: OpenAI) -> None: request = client._build_request( FinalRequestOptions( method="post", url="/foo", **make_request_options( extra_query={"my_query_param": "Foo"}, ), ), ) params = dict(request.url.params) assert params == {"my_query_param": "Foo"} # if both `query` and `extra_query` are given, they are merged request = client._build_request( FinalRequestOptions( method="post", url="/foo", **make_request_options( query={"bar": "1"}, extra_query={"foo": "2"}, ), ), ) params = dict(request.url.params) assert params == {"bar": "1", "foo": "2"} # `extra_query` takes priority over `query` when keys clash request = client._build_request( FinalRequestOptions( method="post", url="/foo", **make_request_options( query={"foo": "1"}, extra_query={"foo": "2"}, ), ), ) params = dict(request.url.params) assert params == {"foo": "2"} def test_multipart_repeating_array(self, client: OpenAI) -> None: request = client._build_request( FinalRequestOptions.construct( method="post", url="/foo", headers={"Content-Type": "multipart/form-data; boundary=6b7ba517decee4a450543ea6ae821c82"}, json_data={"array": ["foo", "bar"]}, files=[("foo.txt", b"hello world")], ) ) assert request.read().split(b"\r\n") == [ b"--6b7ba517decee4a450543ea6ae821c82", b'Content-Disposition: form-data; name="array[]"', b"", b"foo", b"--6b7ba517decee4a450543ea6ae821c82", b'Content-Disposition: form-data; name="array[]"', b"", b"bar", b"--6b7ba517decee4a450543ea6ae821c82", b'Content-Disposition: form-data; name="foo.txt"; filename="upload"', b"Content-Type: application/octet-stream", b"", b"hello world", b"--6b7ba517decee4a450543ea6ae821c82--", b"", ] @pytest.mark.respx(base_url=base_url) def test_binary_content_upload(self, respx_mock: MockRouter, client: OpenAI) -> None: respx_mock.post("/upload").mock(side_effect=mirror_request_content) file_content = b"Hello, this is a test file." response = client.post( "/upload", content=file_content, cast_to=httpx.Response, options={"headers": {"Content-Type": "application/octet-stream"}}, ) assert response.status_code == 200 assert response.request.headers["Content-Type"] == "application/octet-stream" assert response.content == file_content def test_binary_content_upload_with_iterator(self) -> None: file_content = b"Hello, this is a test file." counter = Counter() iterator = _make_sync_iterator([file_content], counter=counter) def mock_handler(request: httpx.Request) -> httpx.Response: assert counter.value == 0, "the request body should not have been read" return httpx.Response(200, content=request.read()) with OpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=httpx.Client(transport=MockTransport(handler=mock_handler)), ) as client: response = client.post( "/upload", content=iterator, cast_to=httpx.Response, options={"headers": {"Content-Type": "application/octet-stream"}}, ) assert response.status_code == 200 assert response.request.headers["Content-Type"] == "application/octet-stream" assert response.content == file_content assert counter.value == 1 @pytest.mark.respx(base_url=base_url) def test_binary_content_upload_with_body_is_deprecated(self, respx_mock: MockRouter, client: OpenAI) -> None: respx_mock.post("/upload").mock(side_effect=mirror_request_content) file_content = b"Hello, this is a test file." with pytest.deprecated_call( match="Passing raw bytes as `body` is deprecated and will be removed in a future version. Please pass raw bytes via the `content` parameter instead." ): response = client.post( "/upload", body=file_content, cast_to=httpx.Response, options={"headers": {"Content-Type": "application/octet-stream"}}, ) assert response.status_code == 200 assert response.request.headers["Content-Type"] == "application/octet-stream" assert response.content == file_content @pytest.mark.respx(base_url=base_url) def test_basic_union_response(self, respx_mock: MockRouter, client: OpenAI) -> None: class Model1(BaseModel): name: str class Model2(BaseModel): foo: str respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) assert response.foo == "bar" @pytest.mark.respx(base_url=base_url) def test_union_response_different_types(self, respx_mock: MockRouter, client: OpenAI) -> None: """Union of objects with the same field name using a different type""" class Model1(BaseModel): foo: int class Model2(BaseModel): foo: str respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) assert response.foo == "bar" respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": 1})) response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model1) assert response.foo == 1 @pytest.mark.respx(base_url=base_url) def test_non_application_json_content_type_for_json_data(self, respx_mock: MockRouter, client: OpenAI) -> None: """ Response that sets Content-Type to something other than application/json but returns json data """ class Model(BaseModel): foo: int respx_mock.get("/foo").mock( return_value=httpx.Response( 200, content=json.dumps({"foo": 2}), headers={"Content-Type": "application/text"}, ) ) response = client.get("/foo", cast_to=Model) assert isinstance(response, Model) assert response.foo == 2 def test_base_url_setter(self) -> None: client = OpenAI(base_url="https://example.com/from_init", api_key=api_key, _strict_response_validation=True) assert client.base_url == "https://example.com/from_init/" client.base_url = "https://example.com/from_setter" # type: ignore[assignment] assert client.base_url == "https://example.com/from_setter/" client.close() def test_base_url_env(self) -> None: with update_env(OPENAI_BASE_URL="http://localhost:5000/from/env"): client = OpenAI(api_key=api_key, _strict_response_validation=True) assert client.base_url == "http://localhost:5000/from/env/" @pytest.mark.parametrize( "client", [ OpenAI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), OpenAI( base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, http_client=httpx.Client(), ), ], ids=["standard", "custom http client"], ) def test_base_url_trailing_slash(self, client: OpenAI) -> None: request = client._build_request( FinalRequestOptions( method="post", url="/foo", json_data={"foo": "bar"}, ), ) assert request.url == "http://localhost:5000/custom/path/foo" client.close() @pytest.mark.parametrize( "client", [ OpenAI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), OpenAI( base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, http_client=httpx.Client(), ), ], ids=["standard", "custom http client"], ) def test_base_url_no_trailing_slash(self, client: OpenAI) -> None: request = client._build_request( FinalRequestOptions( method="post", url="/foo", json_data={"foo": "bar"}, ), ) assert request.url == "http://localhost:5000/custom/path/foo" client.close() @pytest.mark.parametrize( "client", [ OpenAI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), OpenAI( base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, http_client=httpx.Client(), ), ], ids=["standard", "custom http client"], ) def test_absolute_request_url(self, client: OpenAI) -> None: request = client._build_request( FinalRequestOptions( method="post", url="https://myapi.com/foo", json_data={"foo": "bar"}, ), ) assert request.url == "https://myapi.com/foo" client.close() def test_copied_client_does_not_close_http(self) -> None: test_client = OpenAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) assert not test_client.is_closed() copied = test_client.copy() assert copied is not test_client del copied assert not test_client.is_closed() def test_client_context_manager(self) -> None: test_client = OpenAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) with test_client as c2: assert c2 is test_client assert not c2.is_closed() assert not test_client.is_closed() assert test_client.is_closed() @pytest.mark.respx(base_url=base_url) def test_client_response_validation_error(self, respx_mock: MockRouter, client: OpenAI) -> None: class Model(BaseModel): foo: str respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": {"invalid": True}})) with pytest.raises(APIResponseValidationError) as exc: client.get("/foo", cast_to=Model) assert isinstance(exc.value.__cause__, ValidationError) def test_client_max_retries_validation(self) -> None: with pytest.raises(TypeError, match=r"max_retries cannot be None"): OpenAI(base_url=base_url, api_key=api_key, _strict_response_validation=True, max_retries=cast(Any, None)) @pytest.mark.respx(base_url=base_url) def test_default_stream_cls(self, respx_mock: MockRouter, client: OpenAI) -> None: class Model(BaseModel): name: str respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) stream = client.post("/foo", cast_to=Model, stream=True, stream_cls=Stream[Model]) assert isinstance(stream, Stream) stream.response.close() @pytest.mark.respx(base_url=base_url) def test_received_text_for_expected_json(self, respx_mock: MockRouter) -> None: class Model(BaseModel): name: str respx_mock.get("/foo").mock(return_value=httpx.Response(200, text="my-custom-format")) strict_client = OpenAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) with pytest.raises(APIResponseValidationError): strict_client.get("/foo", cast_to=Model) non_strict_client = OpenAI(base_url=base_url, api_key=api_key, _strict_response_validation=False) response = non_strict_client.get("/foo", cast_to=Model) assert isinstance(response, str) # type: ignore[unreachable] strict_client.close() non_strict_client.close() @pytest.mark.parametrize( "remaining_retries,retry_after,timeout", [ [3, "20", 20], [3, "0", 0.5], [3, "-10", 0.5], [3, "60", 60], [3, "61", 0.5], [3, "Fri, 29 Sep 2023 16:26:57 GMT", 20], [3, "Fri, 29 Sep 2023 16:26:37 GMT", 0.5], [3, "Fri, 29 Sep 2023 16:26:27 GMT", 0.5], [3, "Fri, 29 Sep 2023 16:27:37 GMT", 60], [3, "Fri, 29 Sep 2023 16:27:38 GMT", 0.5], [3, "99999999999999999999999999999999999", 0.5], [3, "Zun, 29 Sep 2023 16:26:27 GMT", 0.5], [3, "", 0.5], [2, "", 0.5 * 2.0], [1, "", 0.5 * 4.0], [-1100, "", 8], # test large number potentially overflowing ], ) @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) def test_parse_retry_after_header( self, remaining_retries: int, retry_after: str, timeout: float, client: OpenAI ) -> None: headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3) calculated = client._calculate_retry_timeout(remaining_retries, options, headers) assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] @mock.patch("openai._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, client: OpenAI) -> None: respx_mock.post("/chat/completions").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): client.chat.completions.with_streaming_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", ).__enter__() assert _get_open_connections(client) == 0 @mock.patch("openai._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client: OpenAI) -> None: respx_mock.post("/chat/completions").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): client.chat.completions.with_streaming_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", ).__enter__() assert _get_open_connections(client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("openai._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) @pytest.mark.parametrize("failure_mode", ["status", "exception"]) def test_retries_taken( self, client: OpenAI, failures_before_success: int, failure_mode: Literal["status", "exception"], respx_mock: MockRouter, ) -> None: client = client.with_options(max_retries=4) nb_retries = 0 def retry_handler(_request: httpx.Request) -> httpx.Response: nonlocal nb_retries if nb_retries < failures_before_success: nb_retries += 1 if failure_mode == "exception": raise RuntimeError("oops") return httpx.Response(500) return httpx.Response(200) respx_mock.post("/chat/completions").mock(side_effect=retry_handler) response = client.chat.completions.with_raw_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", ) assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("openai._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_omit_retry_count_header( self, client: OpenAI, failures_before_success: int, respx_mock: MockRouter ) -> None: client = client.with_options(max_retries=4) nb_retries = 0 def retry_handler(_request: httpx.Request) -> httpx.Response: nonlocal nb_retries if nb_retries < failures_before_success: nb_retries += 1 return httpx.Response(500) return httpx.Response(200) respx_mock.post("/chat/completions").mock(side_effect=retry_handler) response = client.chat.completions.with_raw_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", extra_headers={"x-stainless-retry-count": Omit()}, ) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("openai._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_overwrite_retry_count_header( self, client: OpenAI, failures_before_success: int, respx_mock: MockRouter ) -> None: client = client.with_options(max_retries=4) nb_retries = 0 def retry_handler(_request: httpx.Request) -> httpx.Response: nonlocal nb_retries if nb_retries < failures_before_success: nb_retries += 1 return httpx.Response(500) return httpx.Response(200) respx_mock.post("/chat/completions").mock(side_effect=retry_handler) response = client.chat.completions.with_raw_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", extra_headers={"x-stainless-retry-count": "42"}, ) assert response.http_request.headers.get("x-stainless-retry-count") == "42" @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("openai._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_retries_taken_new_response_class( self, client: OpenAI, failures_before_success: int, respx_mock: MockRouter ) -> None: client = client.with_options(max_retries=4) nb_retries = 0 def retry_handler(_request: httpx.Request) -> httpx.Response: nonlocal nb_retries if nb_retries < failures_before_success: nb_retries += 1 return httpx.Response(500) return httpx.Response(200) respx_mock.post("/chat/completions").mock(side_effect=retry_handler) with client.chat.completions.with_streaming_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", ) as response: assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None: # Test that the proxy environment variables are set correctly monkeypatch.setenv("HTTPS_PROXY", "https://example.org") # Delete in case our environment has any proxy env vars set monkeypatch.delenv("HTTP_PROXY", raising=False) monkeypatch.delenv("ALL_PROXY", raising=False) monkeypatch.delenv("NO_PROXY", raising=False) monkeypatch.delenv("http_proxy", raising=False) monkeypatch.delenv("https_proxy", raising=False) monkeypatch.delenv("all_proxy", raising=False) monkeypatch.delenv("no_proxy", raising=False) client = DefaultHttpxClient() mounts = tuple(client._mounts.items()) assert len(mounts) == 1 assert mounts[0][0].pattern == "https://" @pytest.mark.filterwarnings("ignore:.*deprecated.*:DeprecationWarning") def test_default_client_creation(self) -> None: # Ensure that the client can be initialized without any exceptions DefaultHttpxClient( verify=True, cert=None, trust_env=True, http1=True, http2=False, limits=httpx.Limits(max_connections=100, max_keepalive_connections=20), ) @pytest.mark.respx(base_url=base_url) def test_follow_redirects(self, respx_mock: MockRouter, client: OpenAI) -> None: # Test that the default follow_redirects=True allows following redirects respx_mock.post("/redirect").mock( return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) ) respx_mock.get("/redirected").mock(return_value=httpx.Response(200, json={"status": "ok"})) response = client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) assert response.status_code == 200 assert response.json() == {"status": "ok"} @pytest.mark.respx(base_url=base_url) def test_follow_redirects_disabled(self, respx_mock: MockRouter, client: OpenAI) -> None: # Test that follow_redirects=False prevents following redirects respx_mock.post("/redirect").mock( return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) ) with pytest.raises(APIStatusError) as exc_info: client.post("/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response) assert exc_info.value.response.status_code == 302 assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected" def test_api_key_before_after_refresh_provider(self) -> None: client = OpenAI(base_url=base_url, api_key=lambda: "test_bearer_token") assert client.api_key == "" assert "Authorization" not in client.auth_headers client._refresh_api_key() assert client.api_key == "test_bearer_token" assert client.auth_headers.get("Authorization") == "Bearer test_bearer_token" def test_api_key_before_after_refresh_str(self) -> None: client = OpenAI(base_url=base_url, api_key="test_api_key") assert client.auth_headers.get("Authorization") == "Bearer test_api_key" client._refresh_api_key() assert client.auth_headers.get("Authorization") == "Bearer test_api_key" @pytest.mark.respx() def test_api_key_refresh_on_retry(self, respx_mock: MockRouter) -> None: respx_mock.post(base_url + "/chat/completions").mock( side_effect=[ httpx.Response(500, json={"error": "server error"}), httpx.Response(200, json={"foo": "bar"}), ] ) counter = 0 def token_provider() -> str: nonlocal counter counter += 1 if counter == 1: return "first" return "second" client = OpenAI(base_url=base_url, api_key=token_provider) client.chat.completions.create(messages=[], model="gpt-4") calls = cast("list[MockRequestCall]", respx_mock.calls) assert len(calls) == 2 assert calls[0].request.headers.get("Authorization") == "Bearer first" assert calls[1].request.headers.get("Authorization") == "Bearer second" def test_copy_auth(self) -> None: client = OpenAI(base_url=base_url, api_key=lambda: "test_bearer_token_1").copy( api_key=lambda: "test_bearer_token_2" ) client._refresh_api_key() assert client.auth_headers == {"Authorization": "Bearer test_bearer_token_2"} class TestAsyncOpenAI: @pytest.mark.respx(base_url=base_url) async def test_raw_response(self, respx_mock: MockRouter, async_client: AsyncOpenAI) -> None: respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = await async_client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) assert response.json() == {"foo": "bar"} @pytest.mark.respx(base_url=base_url) async def test_raw_response_for_binary(self, respx_mock: MockRouter, async_client: AsyncOpenAI) -> None: respx_mock.post("/foo").mock( return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') ) response = await async_client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) assert response.json() == {"foo": "bar"} def test_copy(self, async_client: AsyncOpenAI) -> None: copied = async_client.copy() assert id(copied) != id(async_client) copied = async_client.copy(api_key="another My API Key") assert copied.api_key == "another My API Key" assert async_client.api_key == "My API Key" def test_copy_default_options(self, async_client: AsyncOpenAI) -> None: # options that have a default are overridden correctly copied = async_client.copy(max_retries=7) assert copied.max_retries == 7 assert async_client.max_retries == 2 copied2 = copied.copy(max_retries=6) assert copied2.max_retries == 6 assert copied.max_retries == 7 # timeout assert isinstance(async_client.timeout, httpx.Timeout) copied = async_client.copy(timeout=None) assert copied.timeout is None assert isinstance(async_client.timeout, httpx.Timeout) async def test_copy_default_headers(self) -> None: client = AsyncOpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} ) assert client.default_headers["X-Foo"] == "bar" # does not override the already given value when not specified copied = client.copy() assert copied.default_headers["X-Foo"] == "bar" # merges already given headers copied = client.copy(default_headers={"X-Bar": "stainless"}) assert copied.default_headers["X-Foo"] == "bar" assert copied.default_headers["X-Bar"] == "stainless" # uses new values for any already given headers copied = client.copy(default_headers={"X-Foo": "stainless"}) assert copied.default_headers["X-Foo"] == "stainless" # set_default_headers # completely overrides already set values copied = client.copy(set_default_headers={}) assert copied.default_headers.get("X-Foo") is None copied = client.copy(set_default_headers={"X-Bar": "Robert"}) assert copied.default_headers["X-Bar"] == "Robert" with pytest.raises( ValueError, match="`default_headers` and `set_default_headers` arguments are mutually exclusive", ): client.copy(set_default_headers={}, default_headers={"X-Foo": "Bar"}) await client.close() async def test_copy_default_query(self) -> None: client = AsyncOpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"foo": "bar"} ) assert _get_params(client)["foo"] == "bar" # does not override the already given value when not specified copied = client.copy() assert _get_params(copied)["foo"] == "bar" # merges already given params copied = client.copy(default_query={"bar": "stainless"}) params = _get_params(copied) assert params["foo"] == "bar" assert params["bar"] == "stainless" # uses new values for any already given headers copied = client.copy(default_query={"foo": "stainless"}) assert _get_params(copied)["foo"] == "stainless" # set_default_query # completely overrides already set values copied = client.copy(set_default_query={}) assert _get_params(copied) == {} copied = client.copy(set_default_query={"bar": "Robert"}) assert _get_params(copied)["bar"] == "Robert" with pytest.raises( ValueError, # TODO: update match="`default_query` and `set_default_query` arguments are mutually exclusive", ): client.copy(set_default_query={}, default_query={"foo": "Bar"}) await client.close() def test_copy_signature(self, async_client: AsyncOpenAI) -> None: # ensure the same parameters that can be passed to the client are defined in the `.copy()` method init_signature = inspect.signature( # mypy doesn't like that we access the `__init__` property. async_client.__init__, # type: ignore[misc] ) copy_signature = inspect.signature(async_client.copy) exclude_params = {"transport", "proxies", "_strict_response_validation"} for name in init_signature.parameters.keys(): if name in exclude_params: continue copy_param = copy_signature.parameters.get(name) assert copy_param is not None, f"copy() signature is missing the {name} param" @pytest.mark.skipif(sys.version_info >= (3, 10), reason="fails because of a memory leak that started from 3.12") def test_copy_build_request(self, async_client: AsyncOpenAI) -> None: options = FinalRequestOptions(method="get", url="/foo") def build_request(options: FinalRequestOptions) -> None: client_copy = async_client.copy() client_copy._build_request(options) # ensure that the machinery is warmed up before tracing starts. build_request(options) gc.collect() tracemalloc.start(1000) snapshot_before = tracemalloc.take_snapshot() ITERATIONS = 10 for _ in range(ITERATIONS): build_request(options) gc.collect() snapshot_after = tracemalloc.take_snapshot() tracemalloc.stop() def add_leak(leaks: list[tracemalloc.StatisticDiff], diff: tracemalloc.StatisticDiff) -> None: if diff.count == 0: # Avoid false positives by considering only leaks (i.e. allocations that persist). return if diff.count % ITERATIONS != 0: # Avoid false positives by considering only leaks that appear per iteration. return for frame in diff.traceback: if any( frame.filename.endswith(fragment) for fragment in [ # to_raw_response_wrapper leaks through the @functools.wraps() decorator. # # removing the decorator fixes the leak for reasons we don't understand. "openai/_legacy_response.py", "openai/_response.py", # pydantic.BaseModel.model_dump || pydantic.BaseModel.dict leak memory for some reason. "openai/_compat.py", # Standard library leaks we don't care about. "/logging/__init__.py", ] ): return leaks.append(diff) leaks: list[tracemalloc.StatisticDiff] = [] for diff in snapshot_after.compare_to(snapshot_before, "traceback"): add_leak(leaks, diff) if leaks: for leak in leaks: print("MEMORY LEAK:", leak) for frame in leak.traceback: print(frame) raise AssertionError() async def test_request_timeout(self, async_client: AsyncOpenAI) -> None: request = async_client._build_request(FinalRequestOptions(method="get", url="/foo")) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT request = async_client._build_request( FinalRequestOptions(method="get", url="/foo", timeout=httpx.Timeout(100.0)) ) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(100.0) async def test_client_timeout_option(self) -> None: client = AsyncOpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, timeout=httpx.Timeout(0) ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(0) await client.close() async def test_http_client_timeout_option(self) -> None: # custom timeout given to the httpx client should be used async with httpx.AsyncClient(timeout=None) as http_client: client = AsyncOpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(None) await client.close() # no timeout given to the httpx client should not use the httpx default async with httpx.AsyncClient() as http_client: client = AsyncOpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT await client.close() # explicitly passing the default timeout currently results in it being ignored async with httpx.AsyncClient(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: client = AsyncOpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT # our default await client.close() def test_invalid_http_client(self) -> None: with pytest.raises(TypeError, match="Invalid `http_client` arg"): with httpx.Client() as http_client: AsyncOpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=cast(Any, http_client), ) async def test_default_headers_option(self) -> None: test_client = AsyncOpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} ) request = test_client._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "bar" assert request.headers.get("x-stainless-lang") == "python" test_client2 = AsyncOpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={ "X-Foo": "stainless", "X-Stainless-Lang": "my-overriding-header", }, ) request = test_client2._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "stainless" assert request.headers.get("x-stainless-lang") == "my-overriding-header" await test_client.close() await test_client2.close() async def test_validate_headers(self) -> None: client = AsyncOpenAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) options = await client._prepare_options(FinalRequestOptions(method="get", url="/foo")) request = client._build_request(options) assert request.headers.get("Authorization") == f"Bearer {api_key}" with pytest.raises(OpenAIError): with update_env(**{"OPENAI_API_KEY": Omit()}): client2 = AsyncOpenAI(base_url=base_url, api_key=None, _strict_response_validation=True) _ = client2 async def test_default_query_option(self) -> None: client = AsyncOpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"query_param": "bar"} ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) url = httpx.URL(request.url) assert dict(url.params) == {"query_param": "bar"} request = client._build_request( FinalRequestOptions( method="get", url="/foo", params={"foo": "baz", "query_param": "overridden"}, ) ) url = httpx.URL(request.url) assert dict(url.params) == {"foo": "baz", "query_param": "overridden"} await client.close() def test_request_extra_json(self, client: OpenAI) -> None: request = client._build_request( FinalRequestOptions( method="post", url="/foo", json_data={"foo": "bar"}, extra_json={"baz": False}, ), ) data = json.loads(request.content.decode("utf-8")) assert data == {"foo": "bar", "baz": False} request = client._build_request( FinalRequestOptions( method="post", url="/foo", extra_json={"baz": False}, ), ) data = json.loads(request.content.decode("utf-8")) assert data == {"baz": False} # `extra_json` takes priority over `json_data` when keys clash request = client._build_request( FinalRequestOptions( method="post", url="/foo", json_data={"foo": "bar", "baz": True}, extra_json={"baz": None}, ), ) data = json.loads(request.content.decode("utf-8")) assert data == {"foo": "bar", "baz": None} def test_request_extra_headers(self, client: OpenAI) -> None: request = client._build_request( FinalRequestOptions( method="post", url="/foo", **make_request_options(extra_headers={"X-Foo": "Foo"}), ), ) assert request.headers.get("X-Foo") == "Foo" # `extra_headers` takes priority over `default_headers` when keys clash request = client.with_options(default_headers={"X-Bar": "true"})._build_request( FinalRequestOptions( method="post", url="/foo", **make_request_options( extra_headers={"X-Bar": "false"}, ), ), ) assert request.headers.get("X-Bar") == "false" def test_request_extra_query(self, client: OpenAI) -> None: request = client._build_request( FinalRequestOptions( method="post", url="/foo", **make_request_options( extra_query={"my_query_param": "Foo"}, ), ), ) params = dict(request.url.params) assert params == {"my_query_param": "Foo"} # if both `query` and `extra_query` are given, they are merged request = client._build_request( FinalRequestOptions( method="post", url="/foo", **make_request_options( query={"bar": "1"}, extra_query={"foo": "2"}, ), ), ) params = dict(request.url.params) assert params == {"bar": "1", "foo": "2"} # `extra_query` takes priority over `query` when keys clash request = client._build_request( FinalRequestOptions( method="post", url="/foo", **make_request_options( query={"foo": "1"}, extra_query={"foo": "2"}, ), ), ) params = dict(request.url.params) assert params == {"foo": "2"} def test_multipart_repeating_array(self, async_client: AsyncOpenAI) -> None: request = async_client._build_request( FinalRequestOptions.construct( method="post", url="/foo", headers={"Content-Type": "multipart/form-data; boundary=6b7ba517decee4a450543ea6ae821c82"}, json_data={"array": ["foo", "bar"]}, files=[("foo.txt", b"hello world")], ) ) assert request.read().split(b"\r\n") == [ b"--6b7ba517decee4a450543ea6ae821c82", b'Content-Disposition: form-data; name="array[]"', b"", b"foo", b"--6b7ba517decee4a450543ea6ae821c82", b'Content-Disposition: form-data; name="array[]"', b"", b"bar", b"--6b7ba517decee4a450543ea6ae821c82", b'Content-Disposition: form-data; name="foo.txt"; filename="upload"', b"Content-Type: application/octet-stream", b"", b"hello world", b"--6b7ba517decee4a450543ea6ae821c82--", b"", ] @pytest.mark.respx(base_url=base_url) async def test_binary_content_upload(self, respx_mock: MockRouter, async_client: AsyncOpenAI) -> None: respx_mock.post("/upload").mock(side_effect=mirror_request_content) file_content = b"Hello, this is a test file." response = await async_client.post( "/upload", content=file_content, cast_to=httpx.Response, options={"headers": {"Content-Type": "application/octet-stream"}}, ) assert response.status_code == 200 assert response.request.headers["Content-Type"] == "application/octet-stream" assert response.content == file_content async def test_binary_content_upload_with_asynciterator(self) -> None: file_content = b"Hello, this is a test file." counter = Counter() iterator = _make_async_iterator([file_content], counter=counter) async def mock_handler(request: httpx.Request) -> httpx.Response: assert counter.value == 0, "the request body should not have been read" return httpx.Response(200, content=await request.aread()) async with AsyncOpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=httpx.AsyncClient(transport=MockTransport(handler=mock_handler)), ) as client: response = await client.post( "/upload", content=iterator, cast_to=httpx.Response, options={"headers": {"Content-Type": "application/octet-stream"}}, ) assert response.status_code == 200 assert response.request.headers["Content-Type"] == "application/octet-stream" assert response.content == file_content assert counter.value == 1 @pytest.mark.respx(base_url=base_url) async def test_binary_content_upload_with_body_is_deprecated( self, respx_mock: MockRouter, async_client: AsyncOpenAI ) -> None: respx_mock.post("/upload").mock(side_effect=mirror_request_content) file_content = b"Hello, this is a test file." with pytest.deprecated_call( match="Passing raw bytes as `body` is deprecated and will be removed in a future version. Please pass raw bytes via the `content` parameter instead." ): response = await async_client.post( "/upload", body=file_content, cast_to=httpx.Response, options={"headers": {"Content-Type": "application/octet-stream"}}, ) assert response.status_code == 200 assert response.request.headers["Content-Type"] == "application/octet-stream" assert response.content == file_content @pytest.mark.respx(base_url=base_url) async def test_basic_union_response(self, respx_mock: MockRouter, async_client: AsyncOpenAI) -> None: class Model1(BaseModel): name: str class Model2(BaseModel): foo: str respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) assert response.foo == "bar" @pytest.mark.respx(base_url=base_url) async def test_union_response_different_types(self, respx_mock: MockRouter, async_client: AsyncOpenAI) -> None: """Union of objects with the same field name using a different type""" class Model1(BaseModel): foo: int class Model2(BaseModel): foo: str respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) assert response.foo == "bar" respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": 1})) response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model1) assert response.foo == 1 @pytest.mark.respx(base_url=base_url) async def test_non_application_json_content_type_for_json_data( self, respx_mock: MockRouter, async_client: AsyncOpenAI ) -> None: """ Response that sets Content-Type to something other than application/json but returns json data """ class Model(BaseModel): foo: int respx_mock.get("/foo").mock( return_value=httpx.Response( 200, content=json.dumps({"foo": 2}), headers={"Content-Type": "application/text"}, ) ) response = await async_client.get("/foo", cast_to=Model) assert isinstance(response, Model) assert response.foo == 2 async def test_base_url_setter(self) -> None: client = AsyncOpenAI( base_url="https://example.com/from_init", api_key=api_key, _strict_response_validation=True ) assert client.base_url == "https://example.com/from_init/" client.base_url = "https://example.com/from_setter" # type: ignore[assignment] assert client.base_url == "https://example.com/from_setter/" await client.close() async def test_base_url_env(self) -> None: with update_env(OPENAI_BASE_URL="http://localhost:5000/from/env"): client = AsyncOpenAI(api_key=api_key, _strict_response_validation=True) assert client.base_url == "http://localhost:5000/from/env/" @pytest.mark.parametrize( "client", [ AsyncOpenAI( base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True ), AsyncOpenAI( base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, http_client=httpx.AsyncClient(), ), ], ids=["standard", "custom http client"], ) async def test_base_url_trailing_slash(self, client: AsyncOpenAI) -> None: request = client._build_request( FinalRequestOptions( method="post", url="/foo", json_data={"foo": "bar"}, ), ) assert request.url == "http://localhost:5000/custom/path/foo" await client.close() @pytest.mark.parametrize( "client", [ AsyncOpenAI( base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True ), AsyncOpenAI( base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, http_client=httpx.AsyncClient(), ), ], ids=["standard", "custom http client"], ) async def test_base_url_no_trailing_slash(self, client: AsyncOpenAI) -> None: request = client._build_request( FinalRequestOptions( method="post", url="/foo", json_data={"foo": "bar"}, ), ) assert request.url == "http://localhost:5000/custom/path/foo" await client.close() @pytest.mark.parametrize( "client", [ AsyncOpenAI( base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True ), AsyncOpenAI( base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, http_client=httpx.AsyncClient(), ), ], ids=["standard", "custom http client"], ) async def test_absolute_request_url(self, client: AsyncOpenAI) -> None: request = client._build_request( FinalRequestOptions( method="post", url="https://myapi.com/foo", json_data={"foo": "bar"}, ), ) assert request.url == "https://myapi.com/foo" await client.close() async def test_copied_client_does_not_close_http(self) -> None: test_client = AsyncOpenAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) assert not test_client.is_closed() copied = test_client.copy() assert copied is not test_client del copied await asyncio.sleep(0.2) assert not test_client.is_closed() async def test_client_context_manager(self) -> None: test_client = AsyncOpenAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) async with test_client as c2: assert c2 is test_client assert not c2.is_closed() assert not test_client.is_closed() assert test_client.is_closed() @pytest.mark.respx(base_url=base_url) async def test_client_response_validation_error(self, respx_mock: MockRouter, async_client: AsyncOpenAI) -> None: class Model(BaseModel): foo: str respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": {"invalid": True}})) with pytest.raises(APIResponseValidationError) as exc: await async_client.get("/foo", cast_to=Model) assert isinstance(exc.value.__cause__, ValidationError) async def test_client_max_retries_validation(self) -> None: with pytest.raises(TypeError, match=r"max_retries cannot be None"): AsyncOpenAI( base_url=base_url, api_key=api_key, _strict_response_validation=True, max_retries=cast(Any, None) ) @pytest.mark.respx(base_url=base_url) async def test_default_stream_cls(self, respx_mock: MockRouter, async_client: AsyncOpenAI) -> None: class Model(BaseModel): name: str respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) stream = await async_client.post("/foo", cast_to=Model, stream=True, stream_cls=AsyncStream[Model]) assert isinstance(stream, AsyncStream) await stream.response.aclose() @pytest.mark.respx(base_url=base_url) async def test_received_text_for_expected_json(self, respx_mock: MockRouter) -> None: class Model(BaseModel): name: str respx_mock.get("/foo").mock(return_value=httpx.Response(200, text="my-custom-format")) strict_client = AsyncOpenAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) with pytest.raises(APIResponseValidationError): await strict_client.get("/foo", cast_to=Model) non_strict_client = AsyncOpenAI(base_url=base_url, api_key=api_key, _strict_response_validation=False) response = await non_strict_client.get("/foo", cast_to=Model) assert isinstance(response, str) # type: ignore[unreachable] await strict_client.close() await non_strict_client.close() @pytest.mark.parametrize( "remaining_retries,retry_after,timeout", [ [3, "20", 20], [3, "0", 0.5], [3, "-10", 0.5], [3, "60", 60], [3, "61", 0.5], [3, "Fri, 29 Sep 2023 16:26:57 GMT", 20], [3, "Fri, 29 Sep 2023 16:26:37 GMT", 0.5], [3, "Fri, 29 Sep 2023 16:26:27 GMT", 0.5], [3, "Fri, 29 Sep 2023 16:27:37 GMT", 60], [3, "Fri, 29 Sep 2023 16:27:38 GMT", 0.5], [3, "99999999999999999999999999999999999", 0.5], [3, "Zun, 29 Sep 2023 16:26:27 GMT", 0.5], [3, "", 0.5], [2, "", 0.5 * 2.0], [1, "", 0.5 * 4.0], [-1100, "", 8], # test large number potentially overflowing ], ) @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) async def test_parse_retry_after_header( self, remaining_retries: int, retry_after: str, timeout: float, async_client: AsyncOpenAI ) -> None: headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3) calculated = async_client._calculate_retry_timeout(remaining_retries, options, headers) assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] @mock.patch("openai._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) async def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, async_client: AsyncOpenAI) -> None: respx_mock.post("/chat/completions").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): await async_client.chat.completions.with_streaming_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", ).__aenter__() assert _get_open_connections(async_client) == 0 @mock.patch("openai._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) async def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, async_client: AsyncOpenAI) -> None: respx_mock.post("/chat/completions").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): await async_client.chat.completions.with_streaming_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", ).__aenter__() assert _get_open_connections(async_client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("openai._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) @pytest.mark.parametrize("failure_mode", ["status", "exception"]) async def test_retries_taken( self, async_client: AsyncOpenAI, failures_before_success: int, failure_mode: Literal["status", "exception"], respx_mock: MockRouter, ) -> None: client = async_client.with_options(max_retries=4) nb_retries = 0 def retry_handler(_request: httpx.Request) -> httpx.Response: nonlocal nb_retries if nb_retries < failures_before_success: nb_retries += 1 if failure_mode == "exception": raise RuntimeError("oops") return httpx.Response(500) return httpx.Response(200) respx_mock.post("/chat/completions").mock(side_effect=retry_handler) response = await client.chat.completions.with_raw_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", ) assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("openai._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) async def test_omit_retry_count_header( self, async_client: AsyncOpenAI, failures_before_success: int, respx_mock: MockRouter ) -> None: client = async_client.with_options(max_retries=4) nb_retries = 0 def retry_handler(_request: httpx.Request) -> httpx.Response: nonlocal nb_retries if nb_retries < failures_before_success: nb_retries += 1 return httpx.Response(500) return httpx.Response(200) respx_mock.post("/chat/completions").mock(side_effect=retry_handler) response = await client.chat.completions.with_raw_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", extra_headers={"x-stainless-retry-count": Omit()}, ) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("openai._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) async def test_overwrite_retry_count_header( self, async_client: AsyncOpenAI, failures_before_success: int, respx_mock: MockRouter ) -> None: client = async_client.with_options(max_retries=4) nb_retries = 0 def retry_handler(_request: httpx.Request) -> httpx.Response: nonlocal nb_retries if nb_retries < failures_before_success: nb_retries += 1 return httpx.Response(500) return httpx.Response(200) respx_mock.post("/chat/completions").mock(side_effect=retry_handler) response = await client.chat.completions.with_raw_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", extra_headers={"x-stainless-retry-count": "42"}, ) assert response.http_request.headers.get("x-stainless-retry-count") == "42" @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("openai._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) async def test_retries_taken_new_response_class( self, async_client: AsyncOpenAI, failures_before_success: int, respx_mock: MockRouter ) -> None: client = async_client.with_options(max_retries=4) nb_retries = 0 def retry_handler(_request: httpx.Request) -> httpx.Response: nonlocal nb_retries if nb_retries < failures_before_success: nb_retries += 1 return httpx.Response(500) return httpx.Response(200) respx_mock.post("/chat/completions").mock(side_effect=retry_handler) async with client.chat.completions.with_streaming_response.create( messages=[ { "content": "string", "role": "developer", } ], model="gpt-5.4", ) as response: assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success async def test_get_platform(self) -> None: platform = await asyncify(get_platform)() assert isinstance(platform, (str, OtherPlatform)) async def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None: # Test that the proxy environment variables are set correctly monkeypatch.setenv("HTTPS_PROXY", "https://example.org") # Delete in case our environment has any proxy env vars set monkeypatch.delenv("HTTP_PROXY", raising=False) monkeypatch.delenv("ALL_PROXY", raising=False) monkeypatch.delenv("NO_PROXY", raising=False) monkeypatch.delenv("http_proxy", raising=False) monkeypatch.delenv("https_proxy", raising=False) monkeypatch.delenv("all_proxy", raising=False) monkeypatch.delenv("no_proxy", raising=False) client = DefaultAsyncHttpxClient() mounts = tuple(client._mounts.items()) assert len(mounts) == 1 assert mounts[0][0].pattern == "https://" @pytest.mark.filterwarnings("ignore:.*deprecated.*:DeprecationWarning") async def test_default_client_creation(self) -> None: # Ensure that the client can be initialized without any exceptions DefaultAsyncHttpxClient( verify=True, cert=None, trust_env=True, http1=True, http2=False, limits=httpx.Limits(max_connections=100, max_keepalive_connections=20), ) @pytest.mark.respx(base_url=base_url) async def test_follow_redirects(self, respx_mock: MockRouter, async_client: AsyncOpenAI) -> None: # Test that the default follow_redirects=True allows following redirects respx_mock.post("/redirect").mock( return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) ) respx_mock.get("/redirected").mock(return_value=httpx.Response(200, json={"status": "ok"})) response = await async_client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) assert response.status_code == 200 assert response.json() == {"status": "ok"} @pytest.mark.respx(base_url=base_url) async def test_follow_redirects_disabled(self, respx_mock: MockRouter, async_client: AsyncOpenAI) -> None: # Test that follow_redirects=False prevents following redirects respx_mock.post("/redirect").mock( return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) ) with pytest.raises(APIStatusError) as exc_info: await async_client.post( "/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response ) assert exc_info.value.response.status_code == 302 assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected" @pytest.mark.asyncio async def test_api_key_before_after_refresh_provider(self) -> None: async def mock_api_key_provider(): return "test_bearer_token" client = AsyncOpenAI(base_url=base_url, api_key=mock_api_key_provider) assert client.api_key == "" assert "Authorization" not in client.auth_headers await client._refresh_api_key() assert client.api_key == "test_bearer_token" assert client.auth_headers.get("Authorization") == "Bearer test_bearer_token" @pytest.mark.asyncio async def test_api_key_before_after_refresh_str(self) -> None: client = AsyncOpenAI(base_url=base_url, api_key="test_api_key") assert client.auth_headers.get("Authorization") == "Bearer test_api_key" await client._refresh_api_key() assert client.auth_headers.get("Authorization") == "Bearer test_api_key" @pytest.mark.asyncio @pytest.mark.respx() async def test_bearer_token_refresh_async(self, respx_mock: MockRouter) -> None: respx_mock.post(base_url + "/chat/completions").mock( side_effect=[ httpx.Response(500, json={"error": "server error"}), httpx.Response(200, json={"foo": "bar"}), ] ) counter = 0 async def token_provider() -> str: nonlocal counter counter += 1 if counter == 1: return "first" return "second" client = AsyncOpenAI(base_url=base_url, api_key=token_provider) await client.chat.completions.create(messages=[], model="gpt-4") calls = cast("list[MockRequestCall]", respx_mock.calls) assert len(calls) == 2 assert calls[0].request.headers.get("Authorization") == "Bearer first" assert calls[1].request.headers.get("Authorization") == "Bearer second" @pytest.mark.asyncio async def test_copy_auth(self) -> None: async def token_provider_1() -> str: return "test_bearer_token_1" async def token_provider_2() -> str: return "test_bearer_token_2" client = AsyncOpenAI(base_url=base_url, api_key=token_provider_1).copy(api_key=token_provider_2) await client._refresh_api_key() assert client.auth_headers == {"Authorization": "Bearer test_bearer_token_2"} ================================================ FILE: tests/test_deepcopy.py ================================================ from openai._utils import deepcopy_minimal def assert_different_identities(obj1: object, obj2: object) -> None: assert obj1 == obj2 assert id(obj1) != id(obj2) def test_simple_dict() -> None: obj1 = {"foo": "bar"} obj2 = deepcopy_minimal(obj1) assert_different_identities(obj1, obj2) def test_nested_dict() -> None: obj1 = {"foo": {"bar": True}} obj2 = deepcopy_minimal(obj1) assert_different_identities(obj1, obj2) assert_different_identities(obj1["foo"], obj2["foo"]) def test_complex_nested_dict() -> None: obj1 = {"foo": {"bar": [{"hello": "world"}]}} obj2 = deepcopy_minimal(obj1) assert_different_identities(obj1, obj2) assert_different_identities(obj1["foo"], obj2["foo"]) assert_different_identities(obj1["foo"]["bar"], obj2["foo"]["bar"]) assert_different_identities(obj1["foo"]["bar"][0], obj2["foo"]["bar"][0]) def test_simple_list() -> None: obj1 = ["a", "b", "c"] obj2 = deepcopy_minimal(obj1) assert_different_identities(obj1, obj2) def test_nested_list() -> None: obj1 = ["a", [1, 2, 3]] obj2 = deepcopy_minimal(obj1) assert_different_identities(obj1, obj2) assert_different_identities(obj1[1], obj2[1]) class MyObject: ... def test_ignores_other_types() -> None: # custom classes my_obj = MyObject() obj1 = {"foo": my_obj} obj2 = deepcopy_minimal(obj1) assert_different_identities(obj1, obj2) assert obj1["foo"] is my_obj # tuples obj3 = ("a", "b") obj4 = deepcopy_minimal(obj3) assert obj3 is obj4 ================================================ FILE: tests/test_extract_files.py ================================================ from __future__ import annotations from typing import Sequence import pytest from openai._types import FileTypes from openai._utils import extract_files def test_removes_files_from_input() -> None: query = {"foo": "bar"} assert extract_files(query, paths=[]) == [] assert query == {"foo": "bar"} query2 = {"foo": b"Bar", "hello": "world"} assert extract_files(query2, paths=[["foo"]]) == [("foo", b"Bar")] assert query2 == {"hello": "world"} query3 = {"foo": {"foo": {"bar": b"Bar"}}, "hello": "world"} assert extract_files(query3, paths=[["foo", "foo", "bar"]]) == [("foo[foo][bar]", b"Bar")] assert query3 == {"foo": {"foo": {}}, "hello": "world"} query4 = {"foo": {"bar": b"Bar", "baz": "foo"}, "hello": "world"} assert extract_files(query4, paths=[["foo", "bar"]]) == [("foo[bar]", b"Bar")] assert query4 == {"hello": "world", "foo": {"baz": "foo"}} def test_multiple_files() -> None: query = {"documents": [{"file": b"My first file"}, {"file": b"My second file"}]} assert extract_files(query, paths=[["documents", "", "file"]]) == [ ("documents[][file]", b"My first file"), ("documents[][file]", b"My second file"), ] assert query == {"documents": [{}, {}]} @pytest.mark.parametrize( "query,paths,expected", [ [ {"foo": {"bar": "baz"}}, [["foo", "", "bar"]], [], ], [ {"foo": ["bar", "baz"]}, [["foo", "bar"]], [], ], [ {"foo": {"bar": "baz"}}, [["foo", "foo"]], [], ], ], ids=["dict expecting array", "array expecting dict", "unknown keys"], ) def test_ignores_incorrect_paths( query: dict[str, object], paths: Sequence[Sequence[str]], expected: list[tuple[str, FileTypes]], ) -> None: assert extract_files(query, paths=paths) == expected ================================================ FILE: tests/test_files.py ================================================ from pathlib import Path import anyio import pytest from dirty_equals import IsDict, IsList, IsBytes, IsTuple from openai._files import to_httpx_files, async_to_httpx_files readme_path = Path(__file__).parent.parent.joinpath("README.md") def test_pathlib_includes_file_name() -> None: result = to_httpx_files({"file": readme_path}) print(result) assert result == IsDict({"file": IsTuple("README.md", IsBytes())}) def test_tuple_input() -> None: result = to_httpx_files([("file", readme_path)]) print(result) assert result == IsList(IsTuple("file", IsTuple("README.md", IsBytes()))) @pytest.mark.asyncio async def test_async_pathlib_includes_file_name() -> None: result = await async_to_httpx_files({"file": readme_path}) print(result) assert result == IsDict({"file": IsTuple("README.md", IsBytes())}) @pytest.mark.asyncio async def test_async_supports_anyio_path() -> None: result = await async_to_httpx_files({"file": anyio.Path(readme_path)}) print(result) assert result == IsDict({"file": IsTuple("README.md", IsBytes())}) @pytest.mark.asyncio async def test_async_tuple_input() -> None: result = await async_to_httpx_files([("file", readme_path)]) print(result) assert result == IsList(IsTuple("file", IsTuple("README.md", IsBytes()))) def test_string_not_allowed() -> None: with pytest.raises(TypeError, match="Expected file types input to be a FileContent type or to be a tuple"): to_httpx_files( { "file": "foo", # type: ignore } ) ================================================ FILE: tests/test_legacy_response.py ================================================ import json from typing import Any, Union, cast from typing_extensions import Annotated import httpx import pytest import pydantic from openai import OpenAI, BaseModel from openai._streaming import Stream from openai._base_client import FinalRequestOptions from openai._legacy_response import LegacyAPIResponse from .utils import rich_print_str class PydanticModel(pydantic.BaseModel): ... def test_response_parse_mismatched_basemodel(client: OpenAI) -> None: response = LegacyAPIResponse( raw=httpx.Response(200, content=b"foo"), client=client, stream=False, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) with pytest.raises( TypeError, match="Pydantic models must subclass our base model type, e.g. `from openai import BaseModel`", ): response.parse(to=PydanticModel) @pytest.mark.parametrize( "content, expected", [ ("false", False), ("true", True), ("False", False), ("True", True), ("TrUe", True), ("FalSe", False), ], ) def test_response_parse_bool(client: OpenAI, content: str, expected: bool) -> None: response = LegacyAPIResponse( raw=httpx.Response(200, content=content), client=client, stream=False, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) result = response.parse(to=bool) assert result is expected def test_response_parse_custom_stream(client: OpenAI) -> None: response = LegacyAPIResponse( raw=httpx.Response(200, content=b"foo"), client=client, stream=True, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) stream = response.parse(to=Stream[int]) assert stream._cast_to == int class CustomModel(BaseModel): foo: str bar: int def test_response_parse_custom_model(client: OpenAI) -> None: response = LegacyAPIResponse( raw=httpx.Response(200, content=json.dumps({"foo": "hello!", "bar": 2})), client=client, stream=False, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) obj = response.parse(to=CustomModel) assert obj.foo == "hello!" assert obj.bar == 2 def test_response_basemodel_request_id(client: OpenAI) -> None: response = LegacyAPIResponse( raw=httpx.Response( 200, headers={"x-request-id": "my-req-id"}, content=json.dumps({"foo": "hello!", "bar": 2}), ), client=client, stream=False, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) obj = response.parse(to=CustomModel) assert obj._request_id == "my-req-id" assert obj.foo == "hello!" assert obj.bar == 2 assert obj.to_dict() == {"foo": "hello!", "bar": 2} assert "_request_id" not in rich_print_str(obj) assert "__exclude_fields__" not in rich_print_str(obj) def test_response_parse_annotated_type(client: OpenAI) -> None: response = LegacyAPIResponse( raw=httpx.Response(200, content=json.dumps({"foo": "hello!", "bar": 2})), client=client, stream=False, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) obj = response.parse( to=cast("type[CustomModel]", Annotated[CustomModel, "random metadata"]), ) assert obj.foo == "hello!" assert obj.bar == 2 class OtherModel(pydantic.BaseModel): a: str @pytest.mark.parametrize("client", [False], indirect=True) # loose validation def test_response_parse_expect_model_union_non_json_content(client: OpenAI) -> None: response = LegacyAPIResponse( raw=httpx.Response(200, content=b"foo", headers={"Content-Type": "application/text"}), client=client, stream=False, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) obj = response.parse(to=cast(Any, Union[CustomModel, OtherModel])) assert isinstance(obj, str) assert obj == "foo" ================================================ FILE: tests/test_models.py ================================================ import json from typing import TYPE_CHECKING, Any, Dict, List, Union, Optional, cast from datetime import datetime, timezone from typing_extensions import Literal, Annotated, TypeAliasType import pytest import pydantic from pydantic import Field from openai._utils import PropertyInfo from openai._compat import PYDANTIC_V1, parse_obj, model_dump, model_json from openai._models import DISCRIMINATOR_CACHE, BaseModel, construct_type class BasicModel(BaseModel): foo: str @pytest.mark.parametrize("value", ["hello", 1], ids=["correct type", "mismatched"]) def test_basic(value: object) -> None: m = BasicModel.construct(foo=value) assert m.foo == value def test_directly_nested_model() -> None: class NestedModel(BaseModel): nested: BasicModel m = NestedModel.construct(nested={"foo": "Foo!"}) assert m.nested.foo == "Foo!" # mismatched types m = NestedModel.construct(nested="hello!") assert cast(Any, m.nested) == "hello!" def test_optional_nested_model() -> None: class NestedModel(BaseModel): nested: Optional[BasicModel] m1 = NestedModel.construct(nested=None) assert m1.nested is None m2 = NestedModel.construct(nested={"foo": "bar"}) assert m2.nested is not None assert m2.nested.foo == "bar" # mismatched types m3 = NestedModel.construct(nested={"foo"}) assert isinstance(cast(Any, m3.nested), set) assert cast(Any, m3.nested) == {"foo"} def test_list_nested_model() -> None: class NestedModel(BaseModel): nested: List[BasicModel] m = NestedModel.construct(nested=[{"foo": "bar"}, {"foo": "2"}]) assert m.nested is not None assert isinstance(m.nested, list) assert len(m.nested) == 2 assert m.nested[0].foo == "bar" assert m.nested[1].foo == "2" # mismatched types m = NestedModel.construct(nested=True) assert cast(Any, m.nested) is True m = NestedModel.construct(nested=[False]) assert cast(Any, m.nested) == [False] def test_optional_list_nested_model() -> None: class NestedModel(BaseModel): nested: Optional[List[BasicModel]] m1 = NestedModel.construct(nested=[{"foo": "bar"}, {"foo": "2"}]) assert m1.nested is not None assert isinstance(m1.nested, list) assert len(m1.nested) == 2 assert m1.nested[0].foo == "bar" assert m1.nested[1].foo == "2" m2 = NestedModel.construct(nested=None) assert m2.nested is None # mismatched types m3 = NestedModel.construct(nested={1}) assert cast(Any, m3.nested) == {1} m4 = NestedModel.construct(nested=[False]) assert cast(Any, m4.nested) == [False] def test_list_optional_items_nested_model() -> None: class NestedModel(BaseModel): nested: List[Optional[BasicModel]] m = NestedModel.construct(nested=[None, {"foo": "bar"}]) assert m.nested is not None assert isinstance(m.nested, list) assert len(m.nested) == 2 assert m.nested[0] is None assert m.nested[1] is not None assert m.nested[1].foo == "bar" # mismatched types m3 = NestedModel.construct(nested="foo") assert cast(Any, m3.nested) == "foo" m4 = NestedModel.construct(nested=[False]) assert cast(Any, m4.nested) == [False] def test_list_mismatched_type() -> None: class NestedModel(BaseModel): nested: List[str] m = NestedModel.construct(nested=False) assert cast(Any, m.nested) is False def test_raw_dictionary() -> None: class NestedModel(BaseModel): nested: Dict[str, str] m = NestedModel.construct(nested={"hello": "world"}) assert m.nested == {"hello": "world"} # mismatched types m = NestedModel.construct(nested=False) assert cast(Any, m.nested) is False def test_nested_dictionary_model() -> None: class NestedModel(BaseModel): nested: Dict[str, BasicModel] m = NestedModel.construct(nested={"hello": {"foo": "bar"}}) assert isinstance(m.nested, dict) assert m.nested["hello"].foo == "bar" # mismatched types m = NestedModel.construct(nested={"hello": False}) assert cast(Any, m.nested["hello"]) is False def test_unknown_fields() -> None: m1 = BasicModel.construct(foo="foo", unknown=1) assert m1.foo == "foo" assert cast(Any, m1).unknown == 1 m2 = BasicModel.construct(foo="foo", unknown={"foo_bar": True}) assert m2.foo == "foo" assert cast(Any, m2).unknown == {"foo_bar": True} assert model_dump(m2) == {"foo": "foo", "unknown": {"foo_bar": True}} def test_strict_validation_unknown_fields() -> None: class Model(BaseModel): foo: str model = parse_obj(Model, dict(foo="hello!", user="Robert")) assert model.foo == "hello!" assert cast(Any, model).user == "Robert" assert model_dump(model) == {"foo": "hello!", "user": "Robert"} def test_aliases() -> None: class Model(BaseModel): my_field: int = Field(alias="myField") m = Model.construct(myField=1) assert m.my_field == 1 # mismatched types m = Model.construct(myField={"hello": False}) assert cast(Any, m.my_field) == {"hello": False} def test_repr() -> None: model = BasicModel(foo="bar") assert str(model) == "BasicModel(foo='bar')" assert repr(model) == "BasicModel(foo='bar')" def test_repr_nested_model() -> None: class Child(BaseModel): name: str age: int class Parent(BaseModel): name: str child: Child model = Parent(name="Robert", child=Child(name="Foo", age=5)) assert str(model) == "Parent(name='Robert', child=Child(name='Foo', age=5))" assert repr(model) == "Parent(name='Robert', child=Child(name='Foo', age=5))" def test_optional_list() -> None: class Submodel(BaseModel): name: str class Model(BaseModel): items: Optional[List[Submodel]] m = Model.construct(items=None) assert m.items is None m = Model.construct(items=[]) assert m.items == [] m = Model.construct(items=[{"name": "Robert"}]) assert m.items is not None assert len(m.items) == 1 assert m.items[0].name == "Robert" def test_nested_union_of_models() -> None: class Submodel1(BaseModel): bar: bool class Submodel2(BaseModel): thing: str class Model(BaseModel): foo: Union[Submodel1, Submodel2] m = Model.construct(foo={"thing": "hello"}) assert isinstance(m.foo, Submodel2) assert m.foo.thing == "hello" def test_nested_union_of_mixed_types() -> None: class Submodel1(BaseModel): bar: bool class Model(BaseModel): foo: Union[Submodel1, Literal[True], Literal["CARD_HOLDER"]] m = Model.construct(foo=True) assert m.foo is True m = Model.construct(foo="CARD_HOLDER") assert m.foo == "CARD_HOLDER" m = Model.construct(foo={"bar": False}) assert isinstance(m.foo, Submodel1) assert m.foo.bar is False def test_nested_union_multiple_variants() -> None: class Submodel1(BaseModel): bar: bool class Submodel2(BaseModel): thing: str class Submodel3(BaseModel): foo: int class Model(BaseModel): foo: Union[Submodel1, Submodel2, None, Submodel3] m = Model.construct(foo={"thing": "hello"}) assert isinstance(m.foo, Submodel2) assert m.foo.thing == "hello" m = Model.construct(foo=None) assert m.foo is None m = Model.construct() assert m.foo is None m = Model.construct(foo={"foo": "1"}) assert isinstance(m.foo, Submodel3) assert m.foo.foo == 1 def test_nested_union_invalid_data() -> None: class Submodel1(BaseModel): level: int class Submodel2(BaseModel): name: str class Model(BaseModel): foo: Union[Submodel1, Submodel2] m = Model.construct(foo=True) assert cast(bool, m.foo) is True m = Model.construct(foo={"name": 3}) if PYDANTIC_V1: assert isinstance(m.foo, Submodel2) assert m.foo.name == "3" else: assert isinstance(m.foo, Submodel1) assert m.foo.name == 3 # type: ignore def test_list_of_unions() -> None: class Submodel1(BaseModel): level: int class Submodel2(BaseModel): name: str class Model(BaseModel): items: List[Union[Submodel1, Submodel2]] m = Model.construct(items=[{"level": 1}, {"name": "Robert"}]) assert len(m.items) == 2 assert isinstance(m.items[0], Submodel1) assert m.items[0].level == 1 assert isinstance(m.items[1], Submodel2) assert m.items[1].name == "Robert" m = Model.construct(items=[{"level": -1}, 156]) assert len(m.items) == 2 assert isinstance(m.items[0], Submodel1) assert m.items[0].level == -1 assert cast(Any, m.items[1]) == 156 def test_union_of_lists() -> None: class SubModel1(BaseModel): level: int class SubModel2(BaseModel): name: str class Model(BaseModel): items: Union[List[SubModel1], List[SubModel2]] # with one valid entry m = Model.construct(items=[{"name": "Robert"}]) assert len(m.items) == 1 assert isinstance(m.items[0], SubModel2) assert m.items[0].name == "Robert" # with two entries pointing to different types m = Model.construct(items=[{"level": 1}, {"name": "Robert"}]) assert len(m.items) == 2 assert isinstance(m.items[0], SubModel1) assert m.items[0].level == 1 assert isinstance(m.items[1], SubModel1) assert cast(Any, m.items[1]).name == "Robert" # with two entries pointing to *completely* different types m = Model.construct(items=[{"level": -1}, 156]) assert len(m.items) == 2 assert isinstance(m.items[0], SubModel1) assert m.items[0].level == -1 assert cast(Any, m.items[1]) == 156 def test_dict_of_union() -> None: class SubModel1(BaseModel): name: str class SubModel2(BaseModel): foo: str class Model(BaseModel): data: Dict[str, Union[SubModel1, SubModel2]] m = Model.construct(data={"hello": {"name": "there"}, "foo": {"foo": "bar"}}) assert len(list(m.data.keys())) == 2 assert isinstance(m.data["hello"], SubModel1) assert m.data["hello"].name == "there" assert isinstance(m.data["foo"], SubModel2) assert m.data["foo"].foo == "bar" # TODO: test mismatched type def test_double_nested_union() -> None: class SubModel1(BaseModel): name: str class SubModel2(BaseModel): bar: str class Model(BaseModel): data: Dict[str, List[Union[SubModel1, SubModel2]]] m = Model.construct(data={"foo": [{"bar": "baz"}, {"name": "Robert"}]}) assert len(m.data["foo"]) == 2 entry1 = m.data["foo"][0] assert isinstance(entry1, SubModel2) assert entry1.bar == "baz" entry2 = m.data["foo"][1] assert isinstance(entry2, SubModel1) assert entry2.name == "Robert" # TODO: test mismatched type def test_union_of_dict() -> None: class SubModel1(BaseModel): name: str class SubModel2(BaseModel): foo: str class Model(BaseModel): data: Union[Dict[str, SubModel1], Dict[str, SubModel2]] m = Model.construct(data={"hello": {"name": "there"}, "foo": {"foo": "bar"}}) assert len(list(m.data.keys())) == 2 assert isinstance(m.data["hello"], SubModel1) assert m.data["hello"].name == "there" assert isinstance(m.data["foo"], SubModel1) assert cast(Any, m.data["foo"]).foo == "bar" def test_iso8601_datetime() -> None: class Model(BaseModel): created_at: datetime expected = datetime(2019, 12, 27, 18, 11, 19, 117000, tzinfo=timezone.utc) if PYDANTIC_V1: expected_json = '{"created_at": "2019-12-27T18:11:19.117000+00:00"}' else: expected_json = '{"created_at":"2019-12-27T18:11:19.117000Z"}' model = Model.construct(created_at="2019-12-27T18:11:19.117Z") assert model.created_at == expected assert model_json(model) == expected_json model = parse_obj(Model, dict(created_at="2019-12-27T18:11:19.117Z")) assert model.created_at == expected assert model_json(model) == expected_json def test_does_not_coerce_int() -> None: class Model(BaseModel): bar: int assert Model.construct(bar=1).bar == 1 assert Model.construct(bar=10.9).bar == 10.9 assert Model.construct(bar="19").bar == "19" # type: ignore[comparison-overlap] assert Model.construct(bar=False).bar is False def test_int_to_float_safe_conversion() -> None: class Model(BaseModel): float_field: float m = Model.construct(float_field=10) assert m.float_field == 10.0 assert isinstance(m.float_field, float) m = Model.construct(float_field=10.12) assert m.float_field == 10.12 assert isinstance(m.float_field, float) # number too big m = Model.construct(float_field=2**53 + 1) assert m.float_field == 2**53 + 1 assert isinstance(m.float_field, int) def test_deprecated_alias() -> None: class Model(BaseModel): resource_id: str = Field(alias="model_id") @property def model_id(self) -> str: return self.resource_id m = Model.construct(model_id="id") assert m.model_id == "id" assert m.resource_id == "id" assert m.resource_id is m.model_id m = parse_obj(Model, {"model_id": "id"}) assert m.model_id == "id" assert m.resource_id == "id" assert m.resource_id is m.model_id def test_omitted_fields() -> None: class Model(BaseModel): resource_id: Optional[str] = None m = Model.construct() assert m.resource_id is None assert "resource_id" not in m.model_fields_set m = Model.construct(resource_id=None) assert m.resource_id is None assert "resource_id" in m.model_fields_set m = Model.construct(resource_id="foo") assert m.resource_id == "foo" assert "resource_id" in m.model_fields_set def test_to_dict() -> None: class Model(BaseModel): foo: Optional[str] = Field(alias="FOO", default=None) m = Model(FOO="hello") assert m.to_dict() == {"FOO": "hello"} assert m.to_dict(use_api_names=False) == {"foo": "hello"} m2 = Model() assert m2.to_dict() == {} assert m2.to_dict(exclude_unset=False) == {"FOO": None} assert m2.to_dict(exclude_unset=False, exclude_none=True) == {} assert m2.to_dict(exclude_unset=False, exclude_defaults=True) == {} m3 = Model(FOO=None) assert m3.to_dict() == {"FOO": None} assert m3.to_dict(exclude_none=True) == {} assert m3.to_dict(exclude_defaults=True) == {} class Model2(BaseModel): created_at: datetime time_str = "2024-03-21T11:39:01.275859" m4 = Model2.construct(created_at=time_str) assert m4.to_dict(mode="python") == {"created_at": datetime.fromisoformat(time_str)} assert m4.to_dict(mode="json") == {"created_at": time_str} if PYDANTIC_V1: with pytest.raises(ValueError, match="warnings is only supported in Pydantic v2"): m.to_dict(warnings=False) def test_forwards_compat_model_dump_method() -> None: class Model(BaseModel): foo: Optional[str] = Field(alias="FOO", default=None) m = Model(FOO="hello") assert m.model_dump() == {"foo": "hello"} assert m.model_dump(include={"bar"}) == {} assert m.model_dump(exclude={"foo"}) == {} assert m.model_dump(by_alias=True) == {"FOO": "hello"} m2 = Model() assert m2.model_dump() == {"foo": None} assert m2.model_dump(exclude_unset=True) == {} assert m2.model_dump(exclude_none=True) == {} assert m2.model_dump(exclude_defaults=True) == {} m3 = Model(FOO=None) assert m3.model_dump() == {"foo": None} assert m3.model_dump(exclude_none=True) == {} if PYDANTIC_V1: with pytest.raises(ValueError, match="round_trip is only supported in Pydantic v2"): m.model_dump(round_trip=True) with pytest.raises(ValueError, match="warnings is only supported in Pydantic v2"): m.model_dump(warnings=False) def test_compat_method_no_error_for_warnings() -> None: class Model(BaseModel): foo: Optional[str] m = Model(foo="hello") assert isinstance(model_dump(m, warnings=False), dict) def test_to_json() -> None: class Model(BaseModel): foo: Optional[str] = Field(alias="FOO", default=None) m = Model(FOO="hello") assert json.loads(m.to_json()) == {"FOO": "hello"} assert json.loads(m.to_json(use_api_names=False)) == {"foo": "hello"} if PYDANTIC_V1: assert m.to_json(indent=None) == '{"FOO": "hello"}' else: assert m.to_json(indent=None) == '{"FOO":"hello"}' m2 = Model() assert json.loads(m2.to_json()) == {} assert json.loads(m2.to_json(exclude_unset=False)) == {"FOO": None} assert json.loads(m2.to_json(exclude_unset=False, exclude_none=True)) == {} assert json.loads(m2.to_json(exclude_unset=False, exclude_defaults=True)) == {} m3 = Model(FOO=None) assert json.loads(m3.to_json()) == {"FOO": None} assert json.loads(m3.to_json(exclude_none=True)) == {} if PYDANTIC_V1: with pytest.raises(ValueError, match="warnings is only supported in Pydantic v2"): m.to_json(warnings=False) def test_forwards_compat_model_dump_json_method() -> None: class Model(BaseModel): foo: Optional[str] = Field(alias="FOO", default=None) m = Model(FOO="hello") assert json.loads(m.model_dump_json()) == {"foo": "hello"} assert json.loads(m.model_dump_json(include={"bar"})) == {} assert json.loads(m.model_dump_json(include={"foo"})) == {"foo": "hello"} assert json.loads(m.model_dump_json(by_alias=True)) == {"FOO": "hello"} assert m.model_dump_json(indent=2) == '{\n "foo": "hello"\n}' m2 = Model() assert json.loads(m2.model_dump_json()) == {"foo": None} assert json.loads(m2.model_dump_json(exclude_unset=True)) == {} assert json.loads(m2.model_dump_json(exclude_none=True)) == {} assert json.loads(m2.model_dump_json(exclude_defaults=True)) == {} m3 = Model(FOO=None) assert json.loads(m3.model_dump_json()) == {"foo": None} assert json.loads(m3.model_dump_json(exclude_none=True)) == {} if PYDANTIC_V1: with pytest.raises(ValueError, match="round_trip is only supported in Pydantic v2"): m.model_dump_json(round_trip=True) with pytest.raises(ValueError, match="warnings is only supported in Pydantic v2"): m.model_dump_json(warnings=False) def test_type_compat() -> None: # our model type can be assigned to Pydantic's model type def takes_pydantic(model: pydantic.BaseModel) -> None: # noqa: ARG001 ... class OurModel(BaseModel): foo: Optional[str] = None takes_pydantic(OurModel()) def test_annotated_types() -> None: class Model(BaseModel): value: str m = construct_type( value={"value": "foo"}, type_=cast(Any, Annotated[Model, "random metadata"]), ) assert isinstance(m, Model) assert m.value == "foo" def test_discriminated_unions_invalid_data() -> None: class A(BaseModel): type: Literal["a"] data: str class B(BaseModel): type: Literal["b"] data: int m = construct_type( value={"type": "b", "data": "foo"}, type_=cast(Any, Annotated[Union[A, B], PropertyInfo(discriminator="type")]), ) assert isinstance(m, B) assert m.type == "b" assert m.data == "foo" # type: ignore[comparison-overlap] m = construct_type( value={"type": "a", "data": 100}, type_=cast(Any, Annotated[Union[A, B], PropertyInfo(discriminator="type")]), ) assert isinstance(m, A) assert m.type == "a" if PYDANTIC_V1: # pydantic v1 automatically converts inputs to strings # if the expected type is a str assert m.data == "100" else: assert m.data == 100 # type: ignore[comparison-overlap] def test_discriminated_unions_unknown_variant() -> None: class A(BaseModel): type: Literal["a"] data: str class B(BaseModel): type: Literal["b"] data: int m = construct_type( value={"type": "c", "data": None, "new_thing": "bar"}, type_=cast(Any, Annotated[Union[A, B], PropertyInfo(discriminator="type")]), ) # just chooses the first variant assert isinstance(m, A) assert m.type == "c" # type: ignore[comparison-overlap] assert m.data == None # type: ignore[unreachable] assert m.new_thing == "bar" def test_discriminated_unions_invalid_data_nested_unions() -> None: class A(BaseModel): type: Literal["a"] data: str class B(BaseModel): type: Literal["b"] data: int class C(BaseModel): type: Literal["c"] data: bool m = construct_type( value={"type": "b", "data": "foo"}, type_=cast(Any, Annotated[Union[Union[A, B], C], PropertyInfo(discriminator="type")]), ) assert isinstance(m, B) assert m.type == "b" assert m.data == "foo" # type: ignore[comparison-overlap] m = construct_type( value={"type": "c", "data": "foo"}, type_=cast(Any, Annotated[Union[Union[A, B], C], PropertyInfo(discriminator="type")]), ) assert isinstance(m, C) assert m.type == "c" assert m.data == "foo" # type: ignore[comparison-overlap] def test_discriminated_unions_with_aliases_invalid_data() -> None: class A(BaseModel): foo_type: Literal["a"] = Field(alias="type") data: str class B(BaseModel): foo_type: Literal["b"] = Field(alias="type") data: int m = construct_type( value={"type": "b", "data": "foo"}, type_=cast(Any, Annotated[Union[A, B], PropertyInfo(discriminator="foo_type")]), ) assert isinstance(m, B) assert m.foo_type == "b" assert m.data == "foo" # type: ignore[comparison-overlap] m = construct_type( value={"type": "a", "data": 100}, type_=cast(Any, Annotated[Union[A, B], PropertyInfo(discriminator="foo_type")]), ) assert isinstance(m, A) assert m.foo_type == "a" if PYDANTIC_V1: # pydantic v1 automatically converts inputs to strings # if the expected type is a str assert m.data == "100" else: assert m.data == 100 # type: ignore[comparison-overlap] def test_discriminated_unions_overlapping_discriminators_invalid_data() -> None: class A(BaseModel): type: Literal["a"] data: bool class B(BaseModel): type: Literal["a"] data: int m = construct_type( value={"type": "a", "data": "foo"}, type_=cast(Any, Annotated[Union[A, B], PropertyInfo(discriminator="type")]), ) assert isinstance(m, B) assert m.type == "a" assert m.data == "foo" # type: ignore[comparison-overlap] def test_discriminated_unions_invalid_data_uses_cache() -> None: class A(BaseModel): type: Literal["a"] data: str class B(BaseModel): type: Literal["b"] data: int UnionType = cast(Any, Union[A, B]) assert not DISCRIMINATOR_CACHE.get(UnionType) m = construct_type( value={"type": "b", "data": "foo"}, type_=cast(Any, Annotated[UnionType, PropertyInfo(discriminator="type")]) ) assert isinstance(m, B) assert m.type == "b" assert m.data == "foo" # type: ignore[comparison-overlap] discriminator = DISCRIMINATOR_CACHE.get(UnionType) assert discriminator is not None m = construct_type( value={"type": "b", "data": "foo"}, type_=cast(Any, Annotated[UnionType, PropertyInfo(discriminator="type")]) ) assert isinstance(m, B) assert m.type == "b" assert m.data == "foo" # type: ignore[comparison-overlap] # if the discriminator details object stays the same between invocations then # we hit the cache assert DISCRIMINATOR_CACHE.get(UnionType) is discriminator @pytest.mark.skipif(PYDANTIC_V1, reason="TypeAliasType is not supported in Pydantic v1") def test_type_alias_type() -> None: Alias = TypeAliasType("Alias", str) # pyright: ignore class Model(BaseModel): alias: Alias union: Union[int, Alias] m = construct_type(value={"alias": "foo", "union": "bar"}, type_=Model) assert isinstance(m, Model) assert isinstance(m.alias, str) assert m.alias == "foo" assert isinstance(m.union, str) assert m.union == "bar" @pytest.mark.skipif(PYDANTIC_V1, reason="TypeAliasType is not supported in Pydantic v1") def test_field_named_cls() -> None: class Model(BaseModel): cls: str m = construct_type(value={"cls": "foo"}, type_=Model) assert isinstance(m, Model) assert isinstance(m.cls, str) def test_discriminated_union_case() -> None: class A(BaseModel): type: Literal["a"] data: bool class B(BaseModel): type: Literal["b"] data: List[Union[A, object]] class ModelA(BaseModel): type: Literal["modelA"] data: int class ModelB(BaseModel): type: Literal["modelB"] required: str data: Union[A, B] # when constructing ModelA | ModelB, value data doesn't match ModelB exactly - missing `required` m = construct_type( value={"type": "modelB", "data": {"type": "a", "data": True}}, type_=cast(Any, Annotated[Union[ModelA, ModelB], PropertyInfo(discriminator="type")]), ) assert isinstance(m, ModelB) def test_nested_discriminated_union() -> None: class InnerType1(BaseModel): type: Literal["type_1"] class InnerModel(BaseModel): inner_value: str class InnerType2(BaseModel): type: Literal["type_2"] some_inner_model: InnerModel class Type1(BaseModel): base_type: Literal["base_type_1"] value: Annotated[ Union[ InnerType1, InnerType2, ], PropertyInfo(discriminator="type"), ] class Type2(BaseModel): base_type: Literal["base_type_2"] T = Annotated[ Union[ Type1, Type2, ], PropertyInfo(discriminator="base_type"), ] model = construct_type( type_=T, value={ "base_type": "base_type_1", "value": { "type": "type_2", }, }, ) assert isinstance(model, Type1) assert isinstance(model.value, InnerType2) @pytest.mark.skipif(PYDANTIC_V1, reason="this is only supported in pydantic v2 for now") def test_extra_properties() -> None: class Item(BaseModel): prop: int class Model(BaseModel): __pydantic_extra__: Dict[str, Item] = Field(init=False) # pyright: ignore[reportIncompatibleVariableOverride] other: str if TYPE_CHECKING: def __getattr__(self, attr: str) -> Item: ... model = construct_type( type_=Model, value={ "a": {"prop": 1}, "other": "foo", }, ) assert isinstance(model, Model) assert model.a.prop == 1 assert isinstance(model.a, Item) assert model.other == "foo" ================================================ FILE: tests/test_module_client.py ================================================ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations import os as _os import httpx import pytest from httpx import URL import openai from openai import DEFAULT_TIMEOUT, DEFAULT_MAX_RETRIES def reset_state() -> None: openai._reset_client() openai.api_key = None or "My API Key" openai.organization = None openai.project = None openai.webhook_secret = None openai.base_url = None openai.timeout = DEFAULT_TIMEOUT openai.max_retries = DEFAULT_MAX_RETRIES openai.default_headers = None openai.default_query = None openai.http_client = None openai.api_type = _os.environ.get("OPENAI_API_TYPE") # type: ignore openai.api_version = None openai.azure_endpoint = None openai.azure_ad_token = None openai.azure_ad_token_provider = None @pytest.fixture(autouse=True) def reset_state_fixture() -> None: reset_state() def test_base_url_option() -> None: assert openai.base_url is None assert openai.completions._client.base_url == URL("https://api.openai.com/v1/") openai.base_url = "http://foo.com" assert openai.base_url == URL("http://foo.com") assert openai.completions._client.base_url == URL("http://foo.com") def test_timeout_option() -> None: assert openai.timeout == openai.DEFAULT_TIMEOUT assert openai.completions._client.timeout == openai.DEFAULT_TIMEOUT openai.timeout = 3 assert openai.timeout == 3 assert openai.completions._client.timeout == 3 def test_max_retries_option() -> None: assert openai.max_retries == openai.DEFAULT_MAX_RETRIES assert openai.completions._client.max_retries == openai.DEFAULT_MAX_RETRIES openai.max_retries = 1 assert openai.max_retries == 1 assert openai.completions._client.max_retries == 1 def test_default_headers_option() -> None: assert openai.default_headers == None openai.default_headers = {"Foo": "Bar"} assert openai.default_headers["Foo"] == "Bar" assert openai.completions._client.default_headers["Foo"] == "Bar" def test_default_query_option() -> None: assert openai.default_query is None assert openai.completions._client._custom_query == {} openai.default_query = {"Foo": {"nested": 1}} assert openai.default_query["Foo"] == {"nested": 1} assert openai.completions._client._custom_query["Foo"] == {"nested": 1} def test_http_client_option() -> None: assert openai.http_client is None original_http_client = openai.completions._client._client assert original_http_client is not None new_client = httpx.Client() openai.http_client = new_client assert openai.completions._client._client is new_client import contextlib from typing import Iterator from openai.lib.azure import AzureOpenAI @contextlib.contextmanager def fresh_env() -> Iterator[None]: old = _os.environ.copy() try: _os.environ.clear() yield finally: _os.environ.clear() _os.environ.update(old) def test_only_api_key_results_in_openai_api() -> None: with fresh_env(): openai.api_type = None openai.api_key = "example API key" assert type(openai.completions._client).__name__ == "_ModuleClient" def test_azure_api_key_env_without_api_version() -> None: with fresh_env(): openai.api_type = None _os.environ["AZURE_OPENAI_API_KEY"] = "example API key" with pytest.raises( ValueError, match=r"Must provide either the `api_version` argument or the `OPENAI_API_VERSION` environment variable", ): openai.completions._client # noqa: B018 def test_azure_api_key_and_version_env() -> None: with fresh_env(): openai.api_type = None _os.environ["AZURE_OPENAI_API_KEY"] = "example API key" _os.environ["OPENAI_API_VERSION"] = "example-version" with pytest.raises( ValueError, match=r"Must provide one of the `base_url` or `azure_endpoint` arguments, or the `AZURE_OPENAI_ENDPOINT` environment variable", ): openai.completions._client # noqa: B018 def test_azure_api_key_version_and_endpoint_env() -> None: with fresh_env(): openai.api_type = None _os.environ["AZURE_OPENAI_API_KEY"] = "example API key" _os.environ["OPENAI_API_VERSION"] = "example-version" _os.environ["AZURE_OPENAI_ENDPOINT"] = "https://www.example" openai.completions._client # noqa: B018 assert openai.api_type == "azure" def test_azure_azure_ad_token_version_and_endpoint_env() -> None: with fresh_env(): openai.api_type = None _os.environ["AZURE_OPENAI_AD_TOKEN"] = "example AD token" _os.environ["OPENAI_API_VERSION"] = "example-version" _os.environ["AZURE_OPENAI_ENDPOINT"] = "https://www.example" client = openai.completions._client assert isinstance(client, AzureOpenAI) assert client._azure_ad_token == "example AD token" def test_azure_azure_ad_token_provider_version_and_endpoint_env() -> None: with fresh_env(): openai.api_type = None _os.environ["OPENAI_API_VERSION"] = "example-version" _os.environ["AZURE_OPENAI_ENDPOINT"] = "https://www.example" openai.azure_ad_token_provider = lambda: "token" client = openai.completions._client assert isinstance(client, AzureOpenAI) assert client._azure_ad_token_provider is not None assert client._azure_ad_token_provider() == "token" ================================================ FILE: tests/test_qs.py ================================================ from typing import Any, cast from functools import partial from urllib.parse import unquote import pytest from openai._qs import Querystring, stringify def test_empty() -> None: assert stringify({}) == "" assert stringify({"a": {}}) == "" assert stringify({"a": {"b": {"c": {}}}}) == "" def test_basic() -> None: assert stringify({"a": 1}) == "a=1" assert stringify({"a": "b"}) == "a=b" assert stringify({"a": True}) == "a=true" assert stringify({"a": False}) == "a=false" assert stringify({"a": 1.23456}) == "a=1.23456" assert stringify({"a": None}) == "" @pytest.mark.parametrize("method", ["class", "function"]) def test_nested_dotted(method: str) -> None: if method == "class": serialise = Querystring(nested_format="dots").stringify else: serialise = partial(stringify, nested_format="dots") assert unquote(serialise({"a": {"b": "c"}})) == "a.b=c" assert unquote(serialise({"a": {"b": "c", "d": "e", "f": "g"}})) == "a.b=c&a.d=e&a.f=g" assert unquote(serialise({"a": {"b": {"c": {"d": "e"}}}})) == "a.b.c.d=e" assert unquote(serialise({"a": {"b": True}})) == "a.b=true" def test_nested_brackets() -> None: assert unquote(stringify({"a": {"b": "c"}})) == "a[b]=c" assert unquote(stringify({"a": {"b": "c", "d": "e", "f": "g"}})) == "a[b]=c&a[d]=e&a[f]=g" assert unquote(stringify({"a": {"b": {"c": {"d": "e"}}}})) == "a[b][c][d]=e" assert unquote(stringify({"a": {"b": True}})) == "a[b]=true" @pytest.mark.parametrize("method", ["class", "function"]) def test_array_comma(method: str) -> None: if method == "class": serialise = Querystring(array_format="comma").stringify else: serialise = partial(stringify, array_format="comma") assert unquote(serialise({"in": ["foo", "bar"]})) == "in=foo,bar" assert unquote(serialise({"a": {"b": [True, False]}})) == "a[b]=true,false" assert unquote(serialise({"a": {"b": [True, False, None, True]}})) == "a[b]=true,false,true" def test_array_repeat() -> None: assert unquote(stringify({"in": ["foo", "bar"]})) == "in=foo&in=bar" assert unquote(stringify({"a": {"b": [True, False]}})) == "a[b]=true&a[b]=false" assert unquote(stringify({"a": {"b": [True, False, None, True]}})) == "a[b]=true&a[b]=false&a[b]=true" assert unquote(stringify({"in": ["foo", {"b": {"c": ["d", "e"]}}]})) == "in=foo&in[b][c]=d&in[b][c]=e" @pytest.mark.parametrize("method", ["class", "function"]) def test_array_brackets(method: str) -> None: if method == "class": serialise = Querystring(array_format="brackets").stringify else: serialise = partial(stringify, array_format="brackets") assert unquote(serialise({"in": ["foo", "bar"]})) == "in[]=foo&in[]=bar" assert unquote(serialise({"a": {"b": [True, False]}})) == "a[b][]=true&a[b][]=false" assert unquote(serialise({"a": {"b": [True, False, None, True]}})) == "a[b][]=true&a[b][]=false&a[b][]=true" def test_unknown_array_format() -> None: with pytest.raises(NotImplementedError, match="Unknown array_format value: foo, choose from comma, repeat"): stringify({"a": ["foo", "bar"]}, array_format=cast(Any, "foo")) ================================================ FILE: tests/test_required_args.py ================================================ from __future__ import annotations import pytest from openai._utils import required_args def test_too_many_positional_params() -> None: @required_args(["a"]) def foo(a: str | None = None) -> str | None: return a with pytest.raises(TypeError, match=r"foo\(\) takes 1 argument\(s\) but 2 were given"): foo("a", "b") # type: ignore def test_positional_param() -> None: @required_args(["a"]) def foo(a: str | None = None) -> str | None: return a assert foo("a") == "a" assert foo(None) is None assert foo(a="b") == "b" with pytest.raises(TypeError, match="Missing required argument: 'a'"): foo() def test_keyword_only_param() -> None: @required_args(["a"]) def foo(*, a: str | None = None) -> str | None: return a assert foo(a="a") == "a" assert foo(a=None) is None assert foo(a="b") == "b" with pytest.raises(TypeError, match="Missing required argument: 'a'"): foo() def test_multiple_params() -> None: @required_args(["a", "b", "c"]) def foo(a: str = "", *, b: str = "", c: str = "") -> str | None: return f"{a} {b} {c}" assert foo(a="a", b="b", c="c") == "a b c" error_message = r"Missing required arguments.*" with pytest.raises(TypeError, match=error_message): foo() with pytest.raises(TypeError, match=error_message): foo(a="a") with pytest.raises(TypeError, match=error_message): foo(b="b") with pytest.raises(TypeError, match=error_message): foo(c="c") with pytest.raises(TypeError, match=r"Missing required argument: 'a'"): foo(b="a", c="c") with pytest.raises(TypeError, match=r"Missing required argument: 'b'"): foo("a", c="c") def test_multiple_variants() -> None: @required_args(["a"], ["b"]) def foo(*, a: str | None = None, b: str | None = None) -> str | None: return a if a is not None else b assert foo(a="foo") == "foo" assert foo(b="bar") == "bar" assert foo(a=None) is None assert foo(b=None) is None # TODO: this error message could probably be improved with pytest.raises( TypeError, match=r"Missing required arguments; Expected either \('a'\) or \('b'\) arguments to be given", ): foo() def test_multiple_params_multiple_variants() -> None: @required_args(["a", "b"], ["c"]) def foo(*, a: str | None = None, b: str | None = None, c: str | None = None) -> str | None: if a is not None: return a if b is not None: return b return c error_message = r"Missing required arguments; Expected either \('a' and 'b'\) or \('c'\) arguments to be given" with pytest.raises(TypeError, match=error_message): foo(a="foo") with pytest.raises(TypeError, match=error_message): foo(b="bar") with pytest.raises(TypeError, match=error_message): foo() assert foo(a=None, b="bar") == "bar" assert foo(c=None) is None assert foo(c="foo") == "foo" ================================================ FILE: tests/test_response.py ================================================ import json from typing import Any, List, Union, cast from typing_extensions import Annotated import httpx import pytest import pydantic from openai import OpenAI, BaseModel, AsyncOpenAI from openai._response import ( APIResponse, BaseAPIResponse, AsyncAPIResponse, BinaryAPIResponse, AsyncBinaryAPIResponse, extract_response_type, ) from openai._streaming import Stream from openai._base_client import FinalRequestOptions from .utils import rich_print_str class ConcreteBaseAPIResponse(APIResponse[bytes]): ... class ConcreteAPIResponse(APIResponse[List[str]]): ... class ConcreteAsyncAPIResponse(APIResponse[httpx.Response]): ... def test_extract_response_type_direct_classes() -> None: assert extract_response_type(BaseAPIResponse[str]) == str assert extract_response_type(APIResponse[str]) == str assert extract_response_type(AsyncAPIResponse[str]) == str def test_extract_response_type_direct_class_missing_type_arg() -> None: with pytest.raises( RuntimeError, match="Expected type to have a type argument at index 0 but it did not", ): extract_response_type(AsyncAPIResponse) def test_extract_response_type_concrete_subclasses() -> None: assert extract_response_type(ConcreteBaseAPIResponse) == bytes assert extract_response_type(ConcreteAPIResponse) == List[str] assert extract_response_type(ConcreteAsyncAPIResponse) == httpx.Response def test_extract_response_type_binary_response() -> None: assert extract_response_type(BinaryAPIResponse) == bytes assert extract_response_type(AsyncBinaryAPIResponse) == bytes class PydanticModel(pydantic.BaseModel): ... def test_response_parse_mismatched_basemodel(client: OpenAI) -> None: response = APIResponse( raw=httpx.Response(200, content=b"foo"), client=client, stream=False, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) with pytest.raises( TypeError, match="Pydantic models must subclass our base model type, e.g. `from openai import BaseModel`", ): response.parse(to=PydanticModel) @pytest.mark.asyncio async def test_async_response_parse_mismatched_basemodel(async_client: AsyncOpenAI) -> None: response = AsyncAPIResponse( raw=httpx.Response(200, content=b"foo"), client=async_client, stream=False, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) with pytest.raises( TypeError, match="Pydantic models must subclass our base model type, e.g. `from openai import BaseModel`", ): await response.parse(to=PydanticModel) def test_response_parse_custom_stream(client: OpenAI) -> None: response = APIResponse( raw=httpx.Response(200, content=b"foo"), client=client, stream=True, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) stream = response.parse(to=Stream[int]) assert stream._cast_to == int @pytest.mark.asyncio async def test_async_response_parse_custom_stream(async_client: AsyncOpenAI) -> None: response = AsyncAPIResponse( raw=httpx.Response(200, content=b"foo"), client=async_client, stream=True, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) stream = await response.parse(to=Stream[int]) assert stream._cast_to == int class CustomModel(BaseModel): foo: str bar: int def test_response_parse_custom_model(client: OpenAI) -> None: response = APIResponse( raw=httpx.Response(200, content=json.dumps({"foo": "hello!", "bar": 2})), client=client, stream=False, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) obj = response.parse(to=CustomModel) assert obj.foo == "hello!" assert obj.bar == 2 @pytest.mark.asyncio async def test_async_response_parse_custom_model(async_client: AsyncOpenAI) -> None: response = AsyncAPIResponse( raw=httpx.Response(200, content=json.dumps({"foo": "hello!", "bar": 2})), client=async_client, stream=False, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) obj = await response.parse(to=CustomModel) assert obj.foo == "hello!" assert obj.bar == 2 def test_response_basemodel_request_id(client: OpenAI) -> None: response = APIResponse( raw=httpx.Response( 200, headers={"x-request-id": "my-req-id"}, content=json.dumps({"foo": "hello!", "bar": 2}), ), client=client, stream=False, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) obj = response.parse(to=CustomModel) assert obj._request_id == "my-req-id" assert obj.foo == "hello!" assert obj.bar == 2 assert obj.to_dict() == {"foo": "hello!", "bar": 2} assert "_request_id" not in rich_print_str(obj) assert "__exclude_fields__" not in rich_print_str(obj) @pytest.mark.asyncio async def test_async_response_basemodel_request_id(client: OpenAI) -> None: response = AsyncAPIResponse( raw=httpx.Response( 200, headers={"x-request-id": "my-req-id"}, content=json.dumps({"foo": "hello!", "bar": 2}), ), client=client, stream=False, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) obj = await response.parse(to=CustomModel) assert obj._request_id == "my-req-id" assert obj.foo == "hello!" assert obj.bar == 2 assert obj.to_dict() == {"foo": "hello!", "bar": 2} def test_response_parse_annotated_type(client: OpenAI) -> None: response = APIResponse( raw=httpx.Response(200, content=json.dumps({"foo": "hello!", "bar": 2})), client=client, stream=False, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) obj = response.parse( to=cast("type[CustomModel]", Annotated[CustomModel, "random metadata"]), ) assert obj.foo == "hello!" assert obj.bar == 2 async def test_async_response_parse_annotated_type(async_client: AsyncOpenAI) -> None: response = AsyncAPIResponse( raw=httpx.Response(200, content=json.dumps({"foo": "hello!", "bar": 2})), client=async_client, stream=False, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) obj = await response.parse( to=cast("type[CustomModel]", Annotated[CustomModel, "random metadata"]), ) assert obj.foo == "hello!" assert obj.bar == 2 @pytest.mark.parametrize( "content, expected", [ ("false", False), ("true", True), ("False", False), ("True", True), ("TrUe", True), ("FalSe", False), ], ) def test_response_parse_bool(client: OpenAI, content: str, expected: bool) -> None: response = APIResponse( raw=httpx.Response(200, content=content), client=client, stream=False, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) result = response.parse(to=bool) assert result is expected @pytest.mark.parametrize( "content, expected", [ ("false", False), ("true", True), ("False", False), ("True", True), ("TrUe", True), ("FalSe", False), ], ) async def test_async_response_parse_bool(client: AsyncOpenAI, content: str, expected: bool) -> None: response = AsyncAPIResponse( raw=httpx.Response(200, content=content), client=client, stream=False, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) result = await response.parse(to=bool) assert result is expected class OtherModel(BaseModel): a: str @pytest.mark.parametrize("client", [False], indirect=True) # loose validation def test_response_parse_expect_model_union_non_json_content(client: OpenAI) -> None: response = APIResponse( raw=httpx.Response(200, content=b"foo", headers={"Content-Type": "application/text"}), client=client, stream=False, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) obj = response.parse(to=cast(Any, Union[CustomModel, OtherModel])) assert isinstance(obj, str) assert obj == "foo" @pytest.mark.asyncio @pytest.mark.parametrize("async_client", [False], indirect=True) # loose validation async def test_async_response_parse_expect_model_union_non_json_content(async_client: AsyncOpenAI) -> None: response = AsyncAPIResponse( raw=httpx.Response(200, content=b"foo", headers={"Content-Type": "application/text"}), client=async_client, stream=False, stream_cls=None, cast_to=str, options=FinalRequestOptions.construct(method="get", url="/foo"), ) obj = await response.parse(to=cast(Any, Union[CustomModel, OtherModel])) assert isinstance(obj, str) assert obj == "foo" ================================================ FILE: tests/test_streaming.py ================================================ from __future__ import annotations from typing import Iterator, AsyncIterator import httpx import pytest from openai import OpenAI, AsyncOpenAI from openai._streaming import Stream, AsyncStream, ServerSentEvent @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) async def test_basic(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: def body() -> Iterator[bytes]: yield b"event: completion\n" yield b'data: {"foo":true}\n' yield b"\n" iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) sse = await iter_next(iterator) assert sse.event == "completion" assert sse.json() == {"foo": True} await assert_empty_iter(iterator) @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) async def test_data_missing_event(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: def body() -> Iterator[bytes]: yield b'data: {"foo":true}\n' yield b"\n" iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) sse = await iter_next(iterator) assert sse.event is None assert sse.json() == {"foo": True} await assert_empty_iter(iterator) @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) async def test_event_missing_data(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b"\n" iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) sse = await iter_next(iterator) assert sse.event == "ping" assert sse.data == "" await assert_empty_iter(iterator) @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) async def test_multiple_events(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b"\n" yield b"event: completion\n" yield b"\n" iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) sse = await iter_next(iterator) assert sse.event == "ping" assert sse.data == "" sse = await iter_next(iterator) assert sse.event == "completion" assert sse.data == "" await assert_empty_iter(iterator) @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) async def test_multiple_events_with_data(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b'data: {"foo":true}\n' yield b"\n" yield b"event: completion\n" yield b'data: {"bar":false}\n' yield b"\n" iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) sse = await iter_next(iterator) assert sse.event == "ping" assert sse.json() == {"foo": True} sse = await iter_next(iterator) assert sse.event == "completion" assert sse.json() == {"bar": False} await assert_empty_iter(iterator) @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) async def test_multiple_data_lines_with_empty_line(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b"data: {\n" yield b'data: "foo":\n' yield b"data: \n" yield b"data:\n" yield b"data: true}\n" yield b"\n\n" iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) sse = await iter_next(iterator) assert sse.event == "ping" assert sse.json() == {"foo": True} assert sse.data == '{\n"foo":\n\n\ntrue}' await assert_empty_iter(iterator) @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) async def test_data_json_escaped_double_new_line(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b'data: {"foo": "my long\\n\\ncontent"}' yield b"\n\n" iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) sse = await iter_next(iterator) assert sse.event == "ping" assert sse.json() == {"foo": "my long\n\ncontent"} await assert_empty_iter(iterator) @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) async def test_multiple_data_lines(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b"data: {\n" yield b'data: "foo":\n' yield b"data: true}\n" yield b"\n\n" iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) sse = await iter_next(iterator) assert sse.event == "ping" assert sse.json() == {"foo": True} await assert_empty_iter(iterator) @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) async def test_special_new_line_character( sync: bool, client: OpenAI, async_client: AsyncOpenAI, ) -> None: def body() -> Iterator[bytes]: yield b'data: {"content":" culpa"}\n' yield b"\n" yield b'data: {"content":" \xe2\x80\xa8"}\n' yield b"\n" yield b'data: {"content":"foo"}\n' yield b"\n" iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) sse = await iter_next(iterator) assert sse.event is None assert sse.json() == {"content": " culpa"} sse = await iter_next(iterator) assert sse.event is None assert sse.json() == {"content": " 
"} sse = await iter_next(iterator) assert sse.event is None assert sse.json() == {"content": "foo"} await assert_empty_iter(iterator) @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) async def test_multi_byte_character_multiple_chunks( sync: bool, client: OpenAI, async_client: AsyncOpenAI, ) -> None: def body() -> Iterator[bytes]: yield b'data: {"content":"' # bytes taken from the string 'известни' and arbitrarily split # so that some multi-byte characters span multiple chunks yield b"\xd0" yield b"\xb8\xd0\xb7\xd0" yield b"\xb2\xd0\xb5\xd1\x81\xd1\x82\xd0\xbd\xd0\xb8" yield b'"}\n' yield b"\n" iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) sse = await iter_next(iterator) assert sse.event is None assert sse.json() == {"content": "известни"} async def to_aiter(iter: Iterator[bytes]) -> AsyncIterator[bytes]: for chunk in iter: yield chunk async def iter_next(iter: Iterator[ServerSentEvent] | AsyncIterator[ServerSentEvent]) -> ServerSentEvent: if isinstance(iter, AsyncIterator): return await iter.__anext__() return next(iter) async def assert_empty_iter(iter: Iterator[ServerSentEvent] | AsyncIterator[ServerSentEvent]) -> None: with pytest.raises((StopAsyncIteration, RuntimeError)): await iter_next(iter) def make_event_iterator( content: Iterator[bytes], *, sync: bool, client: OpenAI, async_client: AsyncOpenAI, ) -> Iterator[ServerSentEvent] | AsyncIterator[ServerSentEvent]: if sync: return Stream(cast_to=object, client=client, response=httpx.Response(200, content=content))._iter_events() return AsyncStream( cast_to=object, client=async_client, response=httpx.Response(200, content=to_aiter(content)) )._iter_events() ================================================ FILE: tests/test_transform.py ================================================ from __future__ import annotations import io import pathlib from typing import Any, Dict, List, Union, TypeVar, Iterable, Optional, cast from datetime import date, datetime from typing_extensions import Required, Annotated, TypedDict import pytest from openai._types import Base64FileInput, omit, not_given from openai._utils import ( PropertyInfo, transform as _transform, parse_datetime, async_transform as _async_transform, ) from openai._compat import PYDANTIC_V1 from openai._models import BaseModel _T = TypeVar("_T") SAMPLE_FILE_PATH = pathlib.Path(__file__).parent.joinpath("sample_file.txt") async def transform( data: _T, expected_type: object, use_async: bool, ) -> _T: if use_async: return await _async_transform(data, expected_type=expected_type) return _transform(data, expected_type=expected_type) parametrize = pytest.mark.parametrize("use_async", [False, True], ids=["sync", "async"]) class Foo1(TypedDict): foo_bar: Annotated[str, PropertyInfo(alias="fooBar")] @parametrize @pytest.mark.asyncio async def test_top_level_alias(use_async: bool) -> None: assert await transform({"foo_bar": "hello"}, expected_type=Foo1, use_async=use_async) == {"fooBar": "hello"} class Foo2(TypedDict): bar: Bar2 class Bar2(TypedDict): this_thing: Annotated[int, PropertyInfo(alias="this__thing")] baz: Annotated[Baz2, PropertyInfo(alias="Baz")] class Baz2(TypedDict): my_baz: Annotated[str, PropertyInfo(alias="myBaz")] @parametrize @pytest.mark.asyncio async def test_recursive_typeddict(use_async: bool) -> None: assert await transform({"bar": {"this_thing": 1}}, Foo2, use_async) == {"bar": {"this__thing": 1}} assert await transform({"bar": {"baz": {"my_baz": "foo"}}}, Foo2, use_async) == {"bar": {"Baz": {"myBaz": "foo"}}} class Foo3(TypedDict): things: List[Bar3] class Bar3(TypedDict): my_field: Annotated[str, PropertyInfo(alias="myField")] @parametrize @pytest.mark.asyncio async def test_list_of_typeddict(use_async: bool) -> None: result = await transform({"things": [{"my_field": "foo"}, {"my_field": "foo2"}]}, Foo3, use_async) assert result == {"things": [{"myField": "foo"}, {"myField": "foo2"}]} class Foo4(TypedDict): foo: Union[Bar4, Baz4] class Bar4(TypedDict): foo_bar: Annotated[str, PropertyInfo(alias="fooBar")] class Baz4(TypedDict): foo_baz: Annotated[str, PropertyInfo(alias="fooBaz")] @parametrize @pytest.mark.asyncio async def test_union_of_typeddict(use_async: bool) -> None: assert await transform({"foo": {"foo_bar": "bar"}}, Foo4, use_async) == {"foo": {"fooBar": "bar"}} assert await transform({"foo": {"foo_baz": "baz"}}, Foo4, use_async) == {"foo": {"fooBaz": "baz"}} assert await transform({"foo": {"foo_baz": "baz", "foo_bar": "bar"}}, Foo4, use_async) == { "foo": {"fooBaz": "baz", "fooBar": "bar"} } class Foo5(TypedDict): foo: Annotated[Union[Bar4, List[Baz4]], PropertyInfo(alias="FOO")] class Bar5(TypedDict): foo_bar: Annotated[str, PropertyInfo(alias="fooBar")] class Baz5(TypedDict): foo_baz: Annotated[str, PropertyInfo(alias="fooBaz")] @parametrize @pytest.mark.asyncio async def test_union_of_list(use_async: bool) -> None: assert await transform({"foo": {"foo_bar": "bar"}}, Foo5, use_async) == {"FOO": {"fooBar": "bar"}} assert await transform( { "foo": [ {"foo_baz": "baz"}, {"foo_baz": "baz"}, ] }, Foo5, use_async, ) == {"FOO": [{"fooBaz": "baz"}, {"fooBaz": "baz"}]} class Foo6(TypedDict): bar: Annotated[str, PropertyInfo(alias="Bar")] @parametrize @pytest.mark.asyncio async def test_includes_unknown_keys(use_async: bool) -> None: assert await transform({"bar": "bar", "baz_": {"FOO": 1}}, Foo6, use_async) == { "Bar": "bar", "baz_": {"FOO": 1}, } class Foo7(TypedDict): bar: Annotated[List[Bar7], PropertyInfo(alias="bAr")] foo: Bar7 class Bar7(TypedDict): foo: str @parametrize @pytest.mark.asyncio async def test_ignores_invalid_input(use_async: bool) -> None: assert await transform({"bar": ""}, Foo7, use_async) == {"bAr": ""} assert await transform({"foo": ""}, Foo7, use_async) == {"foo": ""} class DatetimeDict(TypedDict, total=False): foo: Annotated[datetime, PropertyInfo(format="iso8601")] bar: Annotated[Optional[datetime], PropertyInfo(format="iso8601")] required: Required[Annotated[Optional[datetime], PropertyInfo(format="iso8601")]] list_: Required[Annotated[Optional[List[datetime]], PropertyInfo(format="iso8601")]] union: Annotated[Union[int, datetime], PropertyInfo(format="iso8601")] class DateDict(TypedDict, total=False): foo: Annotated[date, PropertyInfo(format="iso8601")] class DatetimeModel(BaseModel): foo: datetime class DateModel(BaseModel): foo: Optional[date] @parametrize @pytest.mark.asyncio async def test_iso8601_format(use_async: bool) -> None: dt = datetime.fromisoformat("2023-02-23T14:16:36.337692+00:00") tz = "+00:00" if PYDANTIC_V1 else "Z" assert await transform({"foo": dt}, DatetimeDict, use_async) == {"foo": "2023-02-23T14:16:36.337692+00:00"} # type: ignore[comparison-overlap] assert await transform(DatetimeModel(foo=dt), Any, use_async) == {"foo": "2023-02-23T14:16:36.337692" + tz} # type: ignore[comparison-overlap] dt = dt.replace(tzinfo=None) assert await transform({"foo": dt}, DatetimeDict, use_async) == {"foo": "2023-02-23T14:16:36.337692"} # type: ignore[comparison-overlap] assert await transform(DatetimeModel(foo=dt), Any, use_async) == {"foo": "2023-02-23T14:16:36.337692"} # type: ignore[comparison-overlap] assert await transform({"foo": None}, DateDict, use_async) == {"foo": None} # type: ignore[comparison-overlap] assert await transform(DateModel(foo=None), Any, use_async) == {"foo": None} # type: ignore assert await transform({"foo": date.fromisoformat("2023-02-23")}, DateDict, use_async) == {"foo": "2023-02-23"} # type: ignore[comparison-overlap] assert await transform(DateModel(foo=date.fromisoformat("2023-02-23")), DateDict, use_async) == { "foo": "2023-02-23" } # type: ignore[comparison-overlap] @parametrize @pytest.mark.asyncio async def test_optional_iso8601_format(use_async: bool) -> None: dt = datetime.fromisoformat("2023-02-23T14:16:36.337692+00:00") assert await transform({"bar": dt}, DatetimeDict, use_async) == {"bar": "2023-02-23T14:16:36.337692+00:00"} # type: ignore[comparison-overlap] assert await transform({"bar": None}, DatetimeDict, use_async) == {"bar": None} @parametrize @pytest.mark.asyncio async def test_required_iso8601_format(use_async: bool) -> None: dt = datetime.fromisoformat("2023-02-23T14:16:36.337692+00:00") assert await transform({"required": dt}, DatetimeDict, use_async) == { "required": "2023-02-23T14:16:36.337692+00:00" } # type: ignore[comparison-overlap] assert await transform({"required": None}, DatetimeDict, use_async) == {"required": None} @parametrize @pytest.mark.asyncio async def test_union_datetime(use_async: bool) -> None: dt = datetime.fromisoformat("2023-02-23T14:16:36.337692+00:00") assert await transform({"union": dt}, DatetimeDict, use_async) == { # type: ignore[comparison-overlap] "union": "2023-02-23T14:16:36.337692+00:00" } assert await transform({"union": "foo"}, DatetimeDict, use_async) == {"union": "foo"} @parametrize @pytest.mark.asyncio async def test_nested_list_iso6801_format(use_async: bool) -> None: dt1 = datetime.fromisoformat("2023-02-23T14:16:36.337692+00:00") dt2 = parse_datetime("2022-01-15T06:34:23Z") assert await transform({"list_": [dt1, dt2]}, DatetimeDict, use_async) == { # type: ignore[comparison-overlap] "list_": ["2023-02-23T14:16:36.337692+00:00", "2022-01-15T06:34:23+00:00"] } @parametrize @pytest.mark.asyncio async def test_datetime_custom_format(use_async: bool) -> None: dt = parse_datetime("2022-01-15T06:34:23Z") result = await transform(dt, Annotated[datetime, PropertyInfo(format="custom", format_template="%H")], use_async) assert result == "06" # type: ignore[comparison-overlap] class DateDictWithRequiredAlias(TypedDict, total=False): required_prop: Required[Annotated[date, PropertyInfo(format="iso8601", alias="prop")]] @parametrize @pytest.mark.asyncio async def test_datetime_with_alias(use_async: bool) -> None: assert await transform({"required_prop": None}, DateDictWithRequiredAlias, use_async) == {"prop": None} # type: ignore[comparison-overlap] assert await transform( {"required_prop": date.fromisoformat("2023-02-23")}, DateDictWithRequiredAlias, use_async ) == {"prop": "2023-02-23"} # type: ignore[comparison-overlap] class MyModel(BaseModel): foo: str @parametrize @pytest.mark.asyncio async def test_pydantic_model_to_dictionary(use_async: bool) -> None: assert cast(Any, await transform(MyModel(foo="hi!"), Any, use_async)) == {"foo": "hi!"} assert cast(Any, await transform(MyModel.construct(foo="hi!"), Any, use_async)) == {"foo": "hi!"} @parametrize @pytest.mark.asyncio async def test_pydantic_empty_model(use_async: bool) -> None: assert cast(Any, await transform(MyModel.construct(), Any, use_async)) == {} @parametrize @pytest.mark.asyncio async def test_pydantic_unknown_field(use_async: bool) -> None: assert cast(Any, await transform(MyModel.construct(my_untyped_field=True), Any, use_async)) == { "my_untyped_field": True } @parametrize @pytest.mark.asyncio async def test_pydantic_mismatched_types(use_async: bool) -> None: model = MyModel.construct(foo=True) if PYDANTIC_V1: params = await transform(model, Any, use_async) else: with pytest.warns(UserWarning): params = await transform(model, Any, use_async) assert cast(Any, params) == {"foo": True} @parametrize @pytest.mark.asyncio async def test_pydantic_mismatched_object_type(use_async: bool) -> None: model = MyModel.construct(foo=MyModel.construct(hello="world")) if PYDANTIC_V1: params = await transform(model, Any, use_async) else: with pytest.warns(UserWarning): params = await transform(model, Any, use_async) assert cast(Any, params) == {"foo": {"hello": "world"}} class ModelNestedObjects(BaseModel): nested: MyModel @parametrize @pytest.mark.asyncio async def test_pydantic_nested_objects(use_async: bool) -> None: model = ModelNestedObjects.construct(nested={"foo": "stainless"}) assert isinstance(model.nested, MyModel) assert cast(Any, await transform(model, Any, use_async)) == {"nested": {"foo": "stainless"}} class ModelWithDefaultField(BaseModel): foo: str with_none_default: Union[str, None] = None with_str_default: str = "foo" @parametrize @pytest.mark.asyncio async def test_pydantic_default_field(use_async: bool) -> None: # should be excluded when defaults are used model = ModelWithDefaultField.construct() assert model.with_none_default is None assert model.with_str_default == "foo" assert cast(Any, await transform(model, Any, use_async)) == {} # should be included when the default value is explicitly given model = ModelWithDefaultField.construct(with_none_default=None, with_str_default="foo") assert model.with_none_default is None assert model.with_str_default == "foo" assert cast(Any, await transform(model, Any, use_async)) == {"with_none_default": None, "with_str_default": "foo"} # should be included when a non-default value is explicitly given model = ModelWithDefaultField.construct(with_none_default="bar", with_str_default="baz") assert model.with_none_default == "bar" assert model.with_str_default == "baz" assert cast(Any, await transform(model, Any, use_async)) == {"with_none_default": "bar", "with_str_default": "baz"} class TypedDictIterableUnion(TypedDict): foo: Annotated[Union[Bar8, Iterable[Baz8]], PropertyInfo(alias="FOO")] class Bar8(TypedDict): foo_bar: Annotated[str, PropertyInfo(alias="fooBar")] class Baz8(TypedDict): foo_baz: Annotated[str, PropertyInfo(alias="fooBaz")] @parametrize @pytest.mark.asyncio async def test_iterable_of_dictionaries(use_async: bool) -> None: assert await transform({"foo": [{"foo_baz": "bar"}]}, TypedDictIterableUnion, use_async) == { "FOO": [{"fooBaz": "bar"}] } assert cast(Any, await transform({"foo": ({"foo_baz": "bar"},)}, TypedDictIterableUnion, use_async)) == { "FOO": [{"fooBaz": "bar"}] } def my_iter() -> Iterable[Baz8]: yield {"foo_baz": "hello"} yield {"foo_baz": "world"} assert await transform({"foo": my_iter()}, TypedDictIterableUnion, use_async) == { "FOO": [{"fooBaz": "hello"}, {"fooBaz": "world"}] } @parametrize @pytest.mark.asyncio async def test_dictionary_items(use_async: bool) -> None: class DictItems(TypedDict): foo_baz: Annotated[str, PropertyInfo(alias="fooBaz")] assert await transform({"foo": {"foo_baz": "bar"}}, Dict[str, DictItems], use_async) == {"foo": {"fooBaz": "bar"}} class TypedDictIterableUnionStr(TypedDict): foo: Annotated[Union[str, Iterable[Baz8]], PropertyInfo(alias="FOO")] @parametrize @pytest.mark.asyncio async def test_iterable_union_str(use_async: bool) -> None: assert await transform({"foo": "bar"}, TypedDictIterableUnionStr, use_async) == {"FOO": "bar"} assert cast(Any, await transform(iter([{"foo_baz": "bar"}]), Union[str, Iterable[Baz8]], use_async)) == [ {"fooBaz": "bar"} ] class TypedDictBase64Input(TypedDict): foo: Annotated[Union[str, Base64FileInput], PropertyInfo(format="base64")] @parametrize @pytest.mark.asyncio async def test_base64_file_input(use_async: bool) -> None: # strings are left as-is assert await transform({"foo": "bar"}, TypedDictBase64Input, use_async) == {"foo": "bar"} # pathlib.Path is automatically converted to base64 assert await transform({"foo": SAMPLE_FILE_PATH}, TypedDictBase64Input, use_async) == { "foo": "SGVsbG8sIHdvcmxkIQo=" } # type: ignore[comparison-overlap] # io instances are automatically converted to base64 assert await transform({"foo": io.StringIO("Hello, world!")}, TypedDictBase64Input, use_async) == { "foo": "SGVsbG8sIHdvcmxkIQ==" } # type: ignore[comparison-overlap] assert await transform({"foo": io.BytesIO(b"Hello, world!")}, TypedDictBase64Input, use_async) == { "foo": "SGVsbG8sIHdvcmxkIQ==" } # type: ignore[comparison-overlap] @parametrize @pytest.mark.asyncio async def test_transform_skipping(use_async: bool) -> None: # lists of ints are left as-is data = [1, 2, 3] assert await transform(data, List[int], use_async) is data # iterables of ints are converted to a list data = iter([1, 2, 3]) assert await transform(data, Iterable[int], use_async) == [1, 2, 3] @parametrize @pytest.mark.asyncio async def test_strips_notgiven(use_async: bool) -> None: assert await transform({"foo_bar": "bar"}, Foo1, use_async) == {"fooBar": "bar"} assert await transform({"foo_bar": not_given}, Foo1, use_async) == {} @parametrize @pytest.mark.asyncio async def test_strips_omit(use_async: bool) -> None: assert await transform({"foo_bar": "bar"}, Foo1, use_async) == {"fooBar": "bar"} assert await transform({"foo_bar": omit}, Foo1, use_async) == {} ================================================ FILE: tests/test_utils/test_datetime_parse.py ================================================ """ Copied from https://github.com/pydantic/pydantic/blob/v1.10.22/tests/test_datetime_parse.py with modifications so it works without pydantic v1 imports. """ from typing import Type, Union from datetime import date, datetime, timezone, timedelta import pytest from openai._utils import parse_date, parse_datetime def create_tz(minutes: int) -> timezone: return timezone(timedelta(minutes=minutes)) @pytest.mark.parametrize( "value,result", [ # Valid inputs ("1494012444.883309", date(2017, 5, 5)), (b"1494012444.883309", date(2017, 5, 5)), (1_494_012_444.883_309, date(2017, 5, 5)), ("1494012444", date(2017, 5, 5)), (1_494_012_444, date(2017, 5, 5)), (0, date(1970, 1, 1)), ("2012-04-23", date(2012, 4, 23)), (b"2012-04-23", date(2012, 4, 23)), ("2012-4-9", date(2012, 4, 9)), (date(2012, 4, 9), date(2012, 4, 9)), (datetime(2012, 4, 9, 12, 15), date(2012, 4, 9)), # Invalid inputs ("x20120423", ValueError), ("2012-04-56", ValueError), (19_999_999_999, date(2603, 10, 11)), # just before watershed (20_000_000_001, date(1970, 8, 20)), # just after watershed (1_549_316_052, date(2019, 2, 4)), # nowish in s (1_549_316_052_104, date(2019, 2, 4)), # nowish in ms (1_549_316_052_104_324, date(2019, 2, 4)), # nowish in μs (1_549_316_052_104_324_096, date(2019, 2, 4)), # nowish in ns ("infinity", date(9999, 12, 31)), ("inf", date(9999, 12, 31)), (float("inf"), date(9999, 12, 31)), ("infinity ", date(9999, 12, 31)), (int("1" + "0" * 100), date(9999, 12, 31)), (1e1000, date(9999, 12, 31)), ("-infinity", date(1, 1, 1)), ("-inf", date(1, 1, 1)), ("nan", ValueError), ], ) def test_date_parsing(value: Union[str, bytes, int, float], result: Union[date, Type[Exception]]) -> None: if type(result) == type and issubclass(result, Exception): # pyright: ignore[reportUnnecessaryIsInstance] with pytest.raises(result): parse_date(value) else: assert parse_date(value) == result @pytest.mark.parametrize( "value,result", [ # Valid inputs # values in seconds ("1494012444.883309", datetime(2017, 5, 5, 19, 27, 24, 883_309, tzinfo=timezone.utc)), (1_494_012_444.883_309, datetime(2017, 5, 5, 19, 27, 24, 883_309, tzinfo=timezone.utc)), ("1494012444", datetime(2017, 5, 5, 19, 27, 24, tzinfo=timezone.utc)), (b"1494012444", datetime(2017, 5, 5, 19, 27, 24, tzinfo=timezone.utc)), (1_494_012_444, datetime(2017, 5, 5, 19, 27, 24, tzinfo=timezone.utc)), # values in ms ("1494012444000.883309", datetime(2017, 5, 5, 19, 27, 24, 883, tzinfo=timezone.utc)), ("-1494012444000.883309", datetime(1922, 8, 29, 4, 32, 35, 999117, tzinfo=timezone.utc)), (1_494_012_444_000, datetime(2017, 5, 5, 19, 27, 24, tzinfo=timezone.utc)), ("2012-04-23T09:15:00", datetime(2012, 4, 23, 9, 15)), ("2012-4-9 4:8:16", datetime(2012, 4, 9, 4, 8, 16)), ("2012-04-23T09:15:00Z", datetime(2012, 4, 23, 9, 15, 0, 0, timezone.utc)), ("2012-4-9 4:8:16-0320", datetime(2012, 4, 9, 4, 8, 16, 0, create_tz(-200))), ("2012-04-23T10:20:30.400+02:30", datetime(2012, 4, 23, 10, 20, 30, 400_000, create_tz(150))), ("2012-04-23T10:20:30.400+02", datetime(2012, 4, 23, 10, 20, 30, 400_000, create_tz(120))), ("2012-04-23T10:20:30.400-02", datetime(2012, 4, 23, 10, 20, 30, 400_000, create_tz(-120))), (b"2012-04-23T10:20:30.400-02", datetime(2012, 4, 23, 10, 20, 30, 400_000, create_tz(-120))), (datetime(2017, 5, 5), datetime(2017, 5, 5)), (0, datetime(1970, 1, 1, 0, 0, 0, tzinfo=timezone.utc)), # Invalid inputs ("x20120423091500", ValueError), ("2012-04-56T09:15:90", ValueError), ("2012-04-23T11:05:00-25:00", ValueError), (19_999_999_999, datetime(2603, 10, 11, 11, 33, 19, tzinfo=timezone.utc)), # just before watershed (20_000_000_001, datetime(1970, 8, 20, 11, 33, 20, 1000, tzinfo=timezone.utc)), # just after watershed (1_549_316_052, datetime(2019, 2, 4, 21, 34, 12, 0, tzinfo=timezone.utc)), # nowish in s (1_549_316_052_104, datetime(2019, 2, 4, 21, 34, 12, 104_000, tzinfo=timezone.utc)), # nowish in ms (1_549_316_052_104_324, datetime(2019, 2, 4, 21, 34, 12, 104_324, tzinfo=timezone.utc)), # nowish in μs (1_549_316_052_104_324_096, datetime(2019, 2, 4, 21, 34, 12, 104_324, tzinfo=timezone.utc)), # nowish in ns ("infinity", datetime(9999, 12, 31, 23, 59, 59, 999999)), ("inf", datetime(9999, 12, 31, 23, 59, 59, 999999)), ("inf ", datetime(9999, 12, 31, 23, 59, 59, 999999)), (1e50, datetime(9999, 12, 31, 23, 59, 59, 999999)), (float("inf"), datetime(9999, 12, 31, 23, 59, 59, 999999)), ("-infinity", datetime(1, 1, 1, 0, 0)), ("-inf", datetime(1, 1, 1, 0, 0)), ("nan", ValueError), ], ) def test_datetime_parsing(value: Union[str, bytes, int, float], result: Union[datetime, Type[Exception]]) -> None: if type(result) == type and issubclass(result, Exception): # pyright: ignore[reportUnnecessaryIsInstance] with pytest.raises(result): parse_datetime(value) else: assert parse_datetime(value) == result ================================================ FILE: tests/test_utils/test_json.py ================================================ from __future__ import annotations import datetime from typing import Union import pydantic from openai import _compat from openai._utils._json import openapi_dumps class TestOpenapiDumps: def test_basic(self) -> None: data = {"key": "value", "number": 42} json_bytes = openapi_dumps(data) assert json_bytes == b'{"key":"value","number":42}' def test_datetime_serialization(self) -> None: dt = datetime.datetime(2023, 1, 1, 12, 0, 0) data = {"datetime": dt} json_bytes = openapi_dumps(data) assert json_bytes == b'{"datetime":"2023-01-01T12:00:00"}' def test_pydantic_model_serialization(self) -> None: class User(pydantic.BaseModel): first_name: str last_name: str age: int model_instance = User(first_name="John", last_name="Kramer", age=83) data = {"model": model_instance} json_bytes = openapi_dumps(data) assert json_bytes == b'{"model":{"first_name":"John","last_name":"Kramer","age":83}}' def test_pydantic_model_with_default_values(self) -> None: class User(pydantic.BaseModel): name: str role: str = "user" active: bool = True score: int = 0 model_instance = User(name="Alice") data = {"model": model_instance} json_bytes = openapi_dumps(data) assert json_bytes == b'{"model":{"name":"Alice"}}' def test_pydantic_model_with_default_values_overridden(self) -> None: class User(pydantic.BaseModel): name: str role: str = "user" active: bool = True model_instance = User(name="Bob", role="admin", active=False) data = {"model": model_instance} json_bytes = openapi_dumps(data) assert json_bytes == b'{"model":{"name":"Bob","role":"admin","active":false}}' def test_pydantic_model_with_alias(self) -> None: class User(pydantic.BaseModel): first_name: str = pydantic.Field(alias="firstName") last_name: str = pydantic.Field(alias="lastName") model_instance = User(firstName="John", lastName="Doe") data = {"model": model_instance} json_bytes = openapi_dumps(data) assert json_bytes == b'{"model":{"firstName":"John","lastName":"Doe"}}' def test_pydantic_model_with_alias_and_default(self) -> None: class User(pydantic.BaseModel): user_name: str = pydantic.Field(alias="userName") user_role: str = pydantic.Field(default="member", alias="userRole") is_active: bool = pydantic.Field(default=True, alias="isActive") model_instance = User(userName="charlie") data = {"model": model_instance} json_bytes = openapi_dumps(data) assert json_bytes == b'{"model":{"userName":"charlie"}}' model_with_overrides = User(userName="diana", userRole="admin", isActive=False) data = {"model": model_with_overrides} json_bytes = openapi_dumps(data) assert json_bytes == b'{"model":{"userName":"diana","userRole":"admin","isActive":false}}' def test_pydantic_model_with_nested_models_and_defaults(self) -> None: class Address(pydantic.BaseModel): street: str city: str = "Unknown" class User(pydantic.BaseModel): name: str address: Address verified: bool = False if _compat.PYDANTIC_V1: # to handle forward references in Pydantic v1 User.update_forward_refs(**locals()) # type: ignore[reportDeprecated] address = Address(street="123 Main St") user = User(name="Diana", address=address) data = {"user": user} json_bytes = openapi_dumps(data) assert json_bytes == b'{"user":{"name":"Diana","address":{"street":"123 Main St"}}}' address_with_city = Address(street="456 Oak Ave", city="Boston") user_verified = User(name="Eve", address=address_with_city, verified=True) data = {"user": user_verified} json_bytes = openapi_dumps(data) assert ( json_bytes == b'{"user":{"name":"Eve","address":{"street":"456 Oak Ave","city":"Boston"},"verified":true}}' ) def test_pydantic_model_with_optional_fields(self) -> None: class User(pydantic.BaseModel): name: str email: Union[str, None] phone: Union[str, None] model_with_none = User(name="Eve", email=None, phone=None) data = {"model": model_with_none} json_bytes = openapi_dumps(data) assert json_bytes == b'{"model":{"name":"Eve","email":null,"phone":null}}' model_with_values = User(name="Frank", email="frank@example.com", phone=None) data = {"model": model_with_values} json_bytes = openapi_dumps(data) assert json_bytes == b'{"model":{"name":"Frank","email":"frank@example.com","phone":null}}' ================================================ FILE: tests/test_utils/test_logging.py ================================================ import logging from typing import Any, Dict, cast import pytest from openai._utils import SensitiveHeadersFilter @pytest.fixture def logger_with_filter() -> logging.Logger: logger = logging.getLogger("test_logger") logger.setLevel(logging.DEBUG) logger.addFilter(SensitiveHeadersFilter()) return logger def test_keys_redacted(logger_with_filter: logging.Logger, caplog: pytest.LogCaptureFixture) -> None: with caplog.at_level(logging.DEBUG): logger_with_filter.debug( "Request options: %s", { "method": "post", "url": "chat/completions", "headers": {"api-key": "12345", "Authorization": "Bearer token"}, }, ) log_record = cast(Dict[str, Any], caplog.records[0].args) assert log_record["method"] == "post" assert log_record["url"] == "chat/completions" assert log_record["headers"]["api-key"] == "" assert log_record["headers"]["Authorization"] == "" assert ( caplog.messages[0] == "Request options: {'method': 'post', 'url': 'chat/completions', 'headers': {'api-key': '', 'Authorization': ''}}" ) def test_keys_redacted_case_insensitive(logger_with_filter: logging.Logger, caplog: pytest.LogCaptureFixture) -> None: with caplog.at_level(logging.DEBUG): logger_with_filter.debug( "Request options: %s", { "method": "post", "url": "chat/completions", "headers": {"Api-key": "12345", "authorization": "Bearer token"}, }, ) log_record = cast(Dict[str, Any], caplog.records[0].args) assert log_record["method"] == "post" assert log_record["url"] == "chat/completions" assert log_record["headers"]["Api-key"] == "" assert log_record["headers"]["authorization"] == "" assert ( caplog.messages[0] == "Request options: {'method': 'post', 'url': 'chat/completions', 'headers': {'Api-key': '', 'authorization': ''}}" ) def test_no_headers(logger_with_filter: logging.Logger, caplog: pytest.LogCaptureFixture) -> None: with caplog.at_level(logging.DEBUG): logger_with_filter.debug( "Request options: %s", {"method": "post", "url": "chat/completions"}, ) log_record = cast(Dict[str, Any], caplog.records[0].args) assert log_record["method"] == "post" assert log_record["url"] == "chat/completions" assert "api-key" not in log_record assert "Authorization" not in log_record assert caplog.messages[0] == "Request options: {'method': 'post', 'url': 'chat/completions'}" def test_headers_without_sensitive_info(logger_with_filter: logging.Logger, caplog: pytest.LogCaptureFixture) -> None: with caplog.at_level(logging.DEBUG): logger_with_filter.debug( "Request options: %s", { "method": "post", "url": "chat/completions", "headers": {"custom": "value"}, }, ) log_record = cast(Dict[str, Any], caplog.records[0].args) assert log_record["method"] == "post" assert log_record["url"] == "chat/completions" assert log_record["headers"] == {"custom": "value"} assert ( caplog.messages[0] == "Request options: {'method': 'post', 'url': 'chat/completions', 'headers': {'custom': 'value'}}" ) def test_standard_debug_msg(logger_with_filter: logging.Logger, caplog: pytest.LogCaptureFixture) -> None: with caplog.at_level(logging.DEBUG): logger_with_filter.debug("Sending HTTP Request: %s %s", "POST", "chat/completions") assert caplog.messages[0] == "Sending HTTP Request: POST chat/completions" ================================================ FILE: tests/test_utils/test_proxy.py ================================================ import operator from typing import Any from typing_extensions import override from openai._utils import LazyProxy from openai._extras._common import MissingDependencyError class RecursiveLazyProxy(LazyProxy[Any]): @override def __load__(self) -> Any: return self def __call__(self, *_args: Any, **_kwds: Any) -> Any: raise RuntimeError("This should never be called!") def test_recursive_proxy() -> None: proxy = RecursiveLazyProxy() assert repr(proxy) == "RecursiveLazyProxy" assert str(proxy) == "RecursiveLazyProxy" assert dir(proxy) == [] assert type(proxy).__name__ == "RecursiveLazyProxy" assert type(operator.attrgetter("name.foo.bar.baz")(proxy)).__name__ == "RecursiveLazyProxy" def test_isinstance_does_not_error() -> None: class MissingDepsProxy(LazyProxy[Any]): @override def __load__(self) -> Any: raise MissingDependencyError("Mocking missing dependency") proxy = MissingDepsProxy() assert not isinstance(proxy, dict) assert isinstance(proxy, LazyProxy) ================================================ FILE: tests/test_utils/test_typing.py ================================================ from __future__ import annotations from typing import Generic, TypeVar, cast from openai._utils import extract_type_var_from_base _T = TypeVar("_T") _T2 = TypeVar("_T2") _T3 = TypeVar("_T3") class BaseGeneric(Generic[_T]): ... class SubclassGeneric(BaseGeneric[_T]): ... class BaseGenericMultipleTypeArgs(Generic[_T, _T2, _T3]): ... class SubclassGenericMultipleTypeArgs(BaseGenericMultipleTypeArgs[_T, _T2, _T3]): ... class SubclassDifferentOrderGenericMultipleTypeArgs(BaseGenericMultipleTypeArgs[_T2, _T, _T3]): ... def test_extract_type_var() -> None: assert ( extract_type_var_from_base( BaseGeneric[int], index=0, generic_bases=cast("tuple[type, ...]", (BaseGeneric,)), ) == int ) def test_extract_type_var_generic_subclass() -> None: assert ( extract_type_var_from_base( SubclassGeneric[int], index=0, generic_bases=cast("tuple[type, ...]", (BaseGeneric,)), ) == int ) def test_extract_type_var_multiple() -> None: typ = BaseGenericMultipleTypeArgs[int, str, None] generic_bases = cast("tuple[type, ...]", (BaseGenericMultipleTypeArgs,)) assert extract_type_var_from_base(typ, index=0, generic_bases=generic_bases) == int assert extract_type_var_from_base(typ, index=1, generic_bases=generic_bases) == str assert extract_type_var_from_base(typ, index=2, generic_bases=generic_bases) == type(None) def test_extract_type_var_generic_subclass_multiple() -> None: typ = SubclassGenericMultipleTypeArgs[int, str, None] generic_bases = cast("tuple[type, ...]", (BaseGenericMultipleTypeArgs,)) assert extract_type_var_from_base(typ, index=0, generic_bases=generic_bases) == int assert extract_type_var_from_base(typ, index=1, generic_bases=generic_bases) == str assert extract_type_var_from_base(typ, index=2, generic_bases=generic_bases) == type(None) def test_extract_type_var_generic_subclass_different_ordering_multiple() -> None: typ = SubclassDifferentOrderGenericMultipleTypeArgs[int, str, None] generic_bases = cast("tuple[type, ...]", (BaseGenericMultipleTypeArgs,)) assert extract_type_var_from_base(typ, index=0, generic_bases=generic_bases) == int assert extract_type_var_from_base(typ, index=1, generic_bases=generic_bases) == str assert extract_type_var_from_base(typ, index=2, generic_bases=generic_bases) == type(None) ================================================ FILE: tests/test_websocket_connection_options.py ================================================ from openai import types from openai.types import websocket_connection_options def test_submodule_alias_is_preserved() -> None: assert ( websocket_connection_options.WebsocketConnectionOptions is websocket_connection_options.WebSocketConnectionOptions ) def test_public_types_alias_is_preserved() -> None: assert types.WebsocketConnectionOptions is types.WebSocketConnectionOptions def test_beta_realtime_import_still_works_with_old_alias() -> None: from openai.resources.beta.realtime.realtime import Realtime, AsyncRealtime assert Realtime.__name__ == "Realtime" assert AsyncRealtime.__name__ == "AsyncRealtime" ================================================ FILE: tests/utils.py ================================================ from __future__ import annotations import io import os import inspect import traceback import contextlib from typing import Any, TypeVar, Iterator, Sequence, ForwardRef, cast from datetime import date, datetime from typing_extensions import Literal, get_args, get_origin, assert_type import rich from openai._types import Omit, NoneType from openai._utils import ( is_dict, is_list, is_list_type, is_union_type, extract_type_arg, is_sequence_type, is_annotated_type, is_type_alias_type, ) from openai._compat import PYDANTIC_V1, field_outer_type, get_model_fields from openai._models import BaseModel BaseModelT = TypeVar("BaseModelT", bound=BaseModel) def evaluate_forwardref(forwardref: ForwardRef, globalns: dict[str, Any]) -> type: return eval(str(forwardref), globalns) # type: ignore[no-any-return] def assert_matches_model(model: type[BaseModelT], value: BaseModelT, *, path: list[str]) -> bool: for name, field in get_model_fields(model).items(): field_value = getattr(value, name) if PYDANTIC_V1: # in v1 nullability was structured differently # https://docs.pydantic.dev/2.0/migration/#required-optional-and-nullable-fields allow_none = getattr(field, "allow_none", False) else: allow_none = False assert_matches_type( field_outer_type(field), field_value, path=[*path, name], allow_none=allow_none, ) return True # Note: the `path` argument is only used to improve error messages when `--showlocals` is used def assert_matches_type( type_: Any, value: object, *, path: list[str], allow_none: bool = False, ) -> None: if is_type_alias_type(type_): type_ = type_.__value__ # unwrap `Annotated[T, ...]` -> `T` if is_annotated_type(type_): type_ = extract_type_arg(type_, 0) if allow_none and value is None: return if type_ is None or type_ is NoneType: assert value is None return origin = get_origin(type_) or type_ if is_list_type(type_): return _assert_list_type(type_, value) if is_sequence_type(type_): assert isinstance(value, Sequence) inner_type = get_args(type_)[0] for entry in value: # type: ignore assert_type(inner_type, entry) # type: ignore return if origin == str: assert isinstance(value, str) elif origin == int: assert isinstance(value, int) elif origin == bool: assert isinstance(value, bool) elif origin == float: assert isinstance(value, float) elif origin == bytes: assert isinstance(value, bytes) elif origin == datetime: assert isinstance(value, datetime) elif origin == date: assert isinstance(value, date) elif origin == object: # nothing to do here, the expected type is unknown pass elif origin == Literal: assert value in get_args(type_) elif origin == dict: assert is_dict(value) args = get_args(type_) key_type = args[0] items_type = args[1] for key, item in value.items(): assert_matches_type(key_type, key, path=[*path, ""]) assert_matches_type(items_type, item, path=[*path, ""]) elif is_union_type(type_): variants = get_args(type_) try: none_index = variants.index(type(None)) except ValueError: pass else: # special case Optional[T] for better error messages if len(variants) == 2: if value is None: # valid return return assert_matches_type(type_=variants[not none_index], value=value, path=path) for i, variant in enumerate(variants): try: assert_matches_type(variant, value, path=[*path, f"variant {i}"]) return except AssertionError: traceback.print_exc() continue raise AssertionError("Did not match any variants") elif issubclass(origin, BaseModel): assert isinstance(value, type_) assert assert_matches_model(type_, cast(Any, value), path=path) elif inspect.isclass(origin) and origin.__name__ == "HttpxBinaryResponseContent": assert value.__class__.__name__ == "HttpxBinaryResponseContent" else: assert None, f"Unhandled field type: {type_}" def _assert_list_type(type_: type[object], value: object) -> None: assert is_list(value) inner_type = get_args(type_)[0] for entry in value: assert_type(inner_type, entry) # type: ignore def rich_print_str(obj: object) -> str: """Like `rich.print()` but returns the string instead""" buf = io.StringIO() console = rich.console.Console(file=buf, width=120) console.print(obj) return buf.getvalue() @contextlib.contextmanager def update_env(**new_env: str | Omit) -> Iterator[None]: old = os.environ.copy() try: for name, value in new_env.items(): if isinstance(value, Omit): os.environ.pop(name, None) else: os.environ[name] = value yield None finally: os.environ.clear() os.environ.update(old)