mirascope 1.25.7__py3-none-any.whl → 2.0.0a0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mirascope/__init__.py +3 -59
- mirascope/graphs/__init__.py +22 -0
- mirascope/{experimental/graphs → graphs}/finite_state_machine.py +70 -159
- mirascope/llm/__init__.py +206 -16
- mirascope/llm/agents/__init__.py +15 -0
- mirascope/llm/agents/agent.py +97 -0
- mirascope/llm/agents/agent_template.py +45 -0
- mirascope/llm/agents/decorator.py +176 -0
- mirascope/llm/calls/__init__.py +16 -0
- mirascope/llm/calls/base_call.py +33 -0
- mirascope/llm/calls/calls.py +315 -0
- mirascope/llm/calls/decorator.py +255 -0
- mirascope/llm/clients/__init__.py +34 -0
- mirascope/llm/clients/anthropic/__init__.py +11 -0
- mirascope/llm/clients/anthropic/_utils/__init__.py +13 -0
- mirascope/llm/clients/anthropic/_utils/decode.py +244 -0
- mirascope/llm/clients/anthropic/_utils/encode.py +243 -0
- mirascope/llm/clients/anthropic/clients.py +819 -0
- mirascope/llm/clients/anthropic/model_ids.py +8 -0
- mirascope/llm/clients/base/__init__.py +15 -0
- mirascope/llm/clients/base/_utils.py +192 -0
- mirascope/llm/clients/base/client.py +1256 -0
- mirascope/llm/clients/base/kwargs.py +12 -0
- mirascope/llm/clients/base/params.py +93 -0
- mirascope/llm/clients/google/__init__.py +6 -0
- mirascope/llm/clients/google/_utils/__init__.py +13 -0
- mirascope/llm/clients/google/_utils/decode.py +231 -0
- mirascope/llm/clients/google/_utils/encode.py +279 -0
- mirascope/llm/clients/google/clients.py +853 -0
- mirascope/llm/clients/google/message.py +7 -0
- mirascope/llm/clients/google/model_ids.py +15 -0
- mirascope/llm/clients/openai/__init__.py +25 -0
- mirascope/llm/clients/openai/completions/__init__.py +9 -0
- mirascope/llm/clients/openai/completions/_utils/__init__.py +13 -0
- mirascope/llm/clients/openai/completions/_utils/decode.py +187 -0
- mirascope/llm/clients/openai/completions/_utils/encode.py +358 -0
- mirascope/llm/clients/openai/completions/_utils/model_features.py +81 -0
- mirascope/llm/clients/openai/completions/clients.py +833 -0
- mirascope/llm/clients/openai/completions/model_ids.py +8 -0
- mirascope/llm/clients/openai/responses/__init__.py +9 -0
- mirascope/llm/clients/openai/responses/_utils/__init__.py +13 -0
- mirascope/llm/clients/openai/responses/_utils/decode.py +194 -0
- mirascope/llm/clients/openai/responses/_utils/encode.py +333 -0
- mirascope/llm/clients/openai/responses/_utils/model_features.py +87 -0
- mirascope/llm/clients/openai/responses/clients.py +832 -0
- mirascope/llm/clients/openai/responses/model_ids.py +8 -0
- mirascope/llm/clients/openai/shared/__init__.py +7 -0
- mirascope/llm/clients/openai/shared/_utils.py +55 -0
- mirascope/llm/clients/providers.py +175 -0
- mirascope/llm/content/__init__.py +70 -0
- mirascope/llm/content/audio.py +173 -0
- mirascope/llm/content/document.py +94 -0
- mirascope/llm/content/image.py +206 -0
- mirascope/llm/content/text.py +47 -0
- mirascope/llm/content/thought.py +58 -0
- mirascope/llm/content/tool_call.py +63 -0
- mirascope/llm/content/tool_output.py +26 -0
- mirascope/llm/context/__init__.py +6 -0
- mirascope/llm/context/_utils.py +28 -0
- mirascope/llm/context/context.py +24 -0
- mirascope/llm/exceptions.py +105 -0
- mirascope/llm/formatting/__init__.py +22 -0
- mirascope/llm/formatting/_utils.py +74 -0
- mirascope/llm/formatting/format.py +104 -0
- mirascope/llm/formatting/from_call_args.py +30 -0
- mirascope/llm/formatting/partial.py +58 -0
- mirascope/llm/formatting/types.py +109 -0
- mirascope/llm/mcp/__init__.py +5 -0
- mirascope/llm/mcp/client.py +118 -0
- mirascope/llm/messages/__init__.py +32 -0
- mirascope/llm/messages/message.py +182 -0
- mirascope/llm/models/__init__.py +16 -0
- mirascope/llm/models/models.py +1243 -0
- mirascope/llm/prompts/__init__.py +33 -0
- mirascope/llm/prompts/_utils.py +60 -0
- mirascope/llm/prompts/decorator.py +286 -0
- mirascope/llm/prompts/protocols.py +99 -0
- mirascope/llm/responses/__init__.py +57 -0
- mirascope/llm/responses/_utils.py +56 -0
- mirascope/llm/responses/base_response.py +91 -0
- mirascope/llm/responses/base_stream_response.py +697 -0
- mirascope/llm/responses/finish_reason.py +27 -0
- mirascope/llm/responses/response.py +345 -0
- mirascope/llm/responses/root_response.py +177 -0
- mirascope/llm/responses/stream_response.py +572 -0
- mirascope/llm/responses/streams.py +363 -0
- mirascope/llm/tools/__init__.py +40 -0
- mirascope/llm/tools/_utils.py +25 -0
- mirascope/llm/tools/decorator.py +175 -0
- mirascope/llm/tools/protocols.py +96 -0
- mirascope/llm/tools/tool_schema.py +246 -0
- mirascope/llm/tools/toolkit.py +152 -0
- mirascope/llm/tools/tools.py +169 -0
- mirascope/llm/types/__init__.py +22 -0
- mirascope/llm/types/dataclass.py +9 -0
- mirascope/llm/types/jsonable.py +44 -0
- mirascope/llm/types/type_vars.py +19 -0
- mirascope-2.0.0a0.dist-info/METADATA +117 -0
- mirascope-2.0.0a0.dist-info/RECORD +101 -0
- mirascope/beta/__init__.py +0 -3
- mirascope/beta/openai/__init__.py +0 -17
- mirascope/beta/openai/realtime/__init__.py +0 -13
- mirascope/beta/openai/realtime/_utils/__init__.py +0 -3
- mirascope/beta/openai/realtime/_utils/_audio.py +0 -74
- mirascope/beta/openai/realtime/_utils/_protocols.py +0 -50
- mirascope/beta/openai/realtime/realtime.py +0 -500
- mirascope/beta/openai/realtime/recording.py +0 -98
- mirascope/beta/openai/realtime/tool.py +0 -113
- mirascope/beta/rag/__init__.py +0 -24
- mirascope/beta/rag/base/__init__.py +0 -22
- mirascope/beta/rag/base/chunkers/__init__.py +0 -2
- mirascope/beta/rag/base/chunkers/base_chunker.py +0 -37
- mirascope/beta/rag/base/chunkers/text_chunker.py +0 -33
- mirascope/beta/rag/base/config.py +0 -8
- mirascope/beta/rag/base/document.py +0 -11
- mirascope/beta/rag/base/embedders.py +0 -35
- mirascope/beta/rag/base/embedding_params.py +0 -18
- mirascope/beta/rag/base/embedding_response.py +0 -30
- mirascope/beta/rag/base/query_results.py +0 -7
- mirascope/beta/rag/base/vectorstore_params.py +0 -18
- mirascope/beta/rag/base/vectorstores.py +0 -37
- mirascope/beta/rag/chroma/__init__.py +0 -11
- mirascope/beta/rag/chroma/types.py +0 -62
- mirascope/beta/rag/chroma/vectorstores.py +0 -121
- mirascope/beta/rag/cohere/__init__.py +0 -11
- mirascope/beta/rag/cohere/embedders.py +0 -87
- mirascope/beta/rag/cohere/embedding_params.py +0 -29
- mirascope/beta/rag/cohere/embedding_response.py +0 -29
- mirascope/beta/rag/cohere/py.typed +0 -0
- mirascope/beta/rag/openai/__init__.py +0 -11
- mirascope/beta/rag/openai/embedders.py +0 -144
- mirascope/beta/rag/openai/embedding_params.py +0 -18
- mirascope/beta/rag/openai/embedding_response.py +0 -14
- mirascope/beta/rag/openai/py.typed +0 -0
- mirascope/beta/rag/pinecone/__init__.py +0 -19
- mirascope/beta/rag/pinecone/types.py +0 -143
- mirascope/beta/rag/pinecone/vectorstores.py +0 -148
- mirascope/beta/rag/weaviate/__init__.py +0 -6
- mirascope/beta/rag/weaviate/types.py +0 -92
- mirascope/beta/rag/weaviate/vectorstores.py +0 -103
- mirascope/core/__init__.py +0 -109
- mirascope/core/anthropic/__init__.py +0 -31
- mirascope/core/anthropic/_call.py +0 -67
- mirascope/core/anthropic/_call_kwargs.py +0 -13
- mirascope/core/anthropic/_thinking.py +0 -70
- mirascope/core/anthropic/_utils/__init__.py +0 -16
- mirascope/core/anthropic/_utils/_convert_common_call_params.py +0 -25
- mirascope/core/anthropic/_utils/_convert_finish_reason_to_common_finish_reasons.py +0 -21
- mirascope/core/anthropic/_utils/_convert_message_params.py +0 -102
- mirascope/core/anthropic/_utils/_get_json_output.py +0 -31
- mirascope/core/anthropic/_utils/_handle_stream.py +0 -113
- mirascope/core/anthropic/_utils/_message_param_converter.py +0 -154
- mirascope/core/anthropic/_utils/_setup_call.py +0 -146
- mirascope/core/anthropic/call_params.py +0 -44
- mirascope/core/anthropic/call_response.py +0 -226
- mirascope/core/anthropic/call_response_chunk.py +0 -152
- mirascope/core/anthropic/dynamic_config.py +0 -40
- mirascope/core/anthropic/py.typed +0 -0
- mirascope/core/anthropic/stream.py +0 -204
- mirascope/core/anthropic/tool.py +0 -101
- mirascope/core/azure/__init__.py +0 -31
- mirascope/core/azure/_call.py +0 -67
- mirascope/core/azure/_call_kwargs.py +0 -13
- mirascope/core/azure/_utils/__init__.py +0 -14
- mirascope/core/azure/_utils/_convert_common_call_params.py +0 -26
- mirascope/core/azure/_utils/_convert_finish_reason_to_common_finish_reasons.py +0 -21
- mirascope/core/azure/_utils/_convert_message_params.py +0 -121
- mirascope/core/azure/_utils/_get_credential.py +0 -33
- mirascope/core/azure/_utils/_get_json_output.py +0 -27
- mirascope/core/azure/_utils/_handle_stream.py +0 -130
- mirascope/core/azure/_utils/_message_param_converter.py +0 -117
- mirascope/core/azure/_utils/_setup_call.py +0 -183
- mirascope/core/azure/call_params.py +0 -59
- mirascope/core/azure/call_response.py +0 -215
- mirascope/core/azure/call_response_chunk.py +0 -105
- mirascope/core/azure/dynamic_config.py +0 -30
- mirascope/core/azure/py.typed +0 -0
- mirascope/core/azure/stream.py +0 -147
- mirascope/core/azure/tool.py +0 -93
- mirascope/core/base/__init__.py +0 -86
- mirascope/core/base/_call_factory.py +0 -256
- mirascope/core/base/_create.py +0 -253
- mirascope/core/base/_extract.py +0 -175
- mirascope/core/base/_extract_with_tools.py +0 -189
- mirascope/core/base/_partial.py +0 -95
- mirascope/core/base/_utils/__init__.py +0 -92
- mirascope/core/base/_utils/_base_message_param_converter.py +0 -22
- mirascope/core/base/_utils/_base_type.py +0 -26
- mirascope/core/base/_utils/_convert_base_model_to_base_tool.py +0 -48
- mirascope/core/base/_utils/_convert_base_type_to_base_tool.py +0 -24
- mirascope/core/base/_utils/_convert_function_to_base_tool.py +0 -139
- mirascope/core/base/_utils/_convert_messages_to_message_params.py +0 -178
- mirascope/core/base/_utils/_convert_provider_finish_reason_to_finish_reason.py +0 -20
- mirascope/core/base/_utils/_default_tool_docstring.py +0 -6
- mirascope/core/base/_utils/_extract_tool_return.py +0 -42
- mirascope/core/base/_utils/_fn_is_async.py +0 -24
- mirascope/core/base/_utils/_format_template.py +0 -32
- mirascope/core/base/_utils/_get_audio_type.py +0 -18
- mirascope/core/base/_utils/_get_common_usage.py +0 -20
- mirascope/core/base/_utils/_get_create_fn_or_async_create_fn.py +0 -137
- mirascope/core/base/_utils/_get_document_type.py +0 -7
- mirascope/core/base/_utils/_get_dynamic_configuration.py +0 -69
- mirascope/core/base/_utils/_get_fields_from_call_args.py +0 -34
- mirascope/core/base/_utils/_get_fn_args.py +0 -23
- mirascope/core/base/_utils/_get_image_dimensions.py +0 -39
- mirascope/core/base/_utils/_get_image_type.py +0 -26
- mirascope/core/base/_utils/_get_metadata.py +0 -17
- mirascope/core/base/_utils/_get_possible_user_message_param.py +0 -21
- mirascope/core/base/_utils/_get_prompt_template.py +0 -28
- mirascope/core/base/_utils/_get_template_values.py +0 -51
- mirascope/core/base/_utils/_get_template_variables.py +0 -38
- mirascope/core/base/_utils/_get_unsupported_tool_config_keys.py +0 -10
- mirascope/core/base/_utils/_is_prompt_template.py +0 -24
- mirascope/core/base/_utils/_json_mode_content.py +0 -17
- mirascope/core/base/_utils/_messages_decorator.py +0 -121
- mirascope/core/base/_utils/_parse_content_template.py +0 -323
- mirascope/core/base/_utils/_parse_prompt_messages.py +0 -63
- mirascope/core/base/_utils/_pil_image_to_bytes.py +0 -13
- mirascope/core/base/_utils/_protocols.py +0 -901
- mirascope/core/base/_utils/_setup_call.py +0 -79
- mirascope/core/base/_utils/_setup_extract_tool.py +0 -30
- mirascope/core/base/call_kwargs.py +0 -13
- mirascope/core/base/call_params.py +0 -36
- mirascope/core/base/call_response.py +0 -338
- mirascope/core/base/call_response_chunk.py +0 -130
- mirascope/core/base/dynamic_config.py +0 -82
- mirascope/core/base/from_call_args.py +0 -30
- mirascope/core/base/merge_decorators.py +0 -59
- mirascope/core/base/message_param.py +0 -175
- mirascope/core/base/messages.py +0 -116
- mirascope/core/base/metadata.py +0 -13
- mirascope/core/base/prompt.py +0 -497
- mirascope/core/base/response_model_config_dict.py +0 -9
- mirascope/core/base/stream.py +0 -479
- mirascope/core/base/stream_config.py +0 -11
- mirascope/core/base/structured_stream.py +0 -296
- mirascope/core/base/tool.py +0 -214
- mirascope/core/base/toolkit.py +0 -176
- mirascope/core/base/types.py +0 -344
- mirascope/core/bedrock/__init__.py +0 -34
- mirascope/core/bedrock/_call.py +0 -68
- mirascope/core/bedrock/_call_kwargs.py +0 -12
- mirascope/core/bedrock/_types.py +0 -104
- mirascope/core/bedrock/_utils/__init__.py +0 -14
- mirascope/core/bedrock/_utils/_convert_common_call_params.py +0 -39
- mirascope/core/bedrock/_utils/_convert_finish_reason_to_common_finish_reasons.py +0 -23
- mirascope/core/bedrock/_utils/_convert_message_params.py +0 -111
- mirascope/core/bedrock/_utils/_get_json_output.py +0 -30
- mirascope/core/bedrock/_utils/_handle_stream.py +0 -104
- mirascope/core/bedrock/_utils/_message_param_converter.py +0 -172
- mirascope/core/bedrock/_utils/_setup_call.py +0 -258
- mirascope/core/bedrock/call_params.py +0 -38
- mirascope/core/bedrock/call_response.py +0 -248
- mirascope/core/bedrock/call_response_chunk.py +0 -111
- mirascope/core/bedrock/dynamic_config.py +0 -37
- mirascope/core/bedrock/py.typed +0 -0
- mirascope/core/bedrock/stream.py +0 -154
- mirascope/core/bedrock/tool.py +0 -100
- mirascope/core/cohere/__init__.py +0 -30
- mirascope/core/cohere/_call.py +0 -67
- mirascope/core/cohere/_call_kwargs.py +0 -11
- mirascope/core/cohere/_types.py +0 -20
- mirascope/core/cohere/_utils/__init__.py +0 -14
- mirascope/core/cohere/_utils/_convert_common_call_params.py +0 -26
- mirascope/core/cohere/_utils/_convert_finish_reason_to_common_finish_reasons.py +0 -24
- mirascope/core/cohere/_utils/_convert_message_params.py +0 -32
- mirascope/core/cohere/_utils/_get_json_output.py +0 -30
- mirascope/core/cohere/_utils/_handle_stream.py +0 -35
- mirascope/core/cohere/_utils/_message_param_converter.py +0 -54
- mirascope/core/cohere/_utils/_setup_call.py +0 -150
- mirascope/core/cohere/call_params.py +0 -62
- mirascope/core/cohere/call_response.py +0 -205
- mirascope/core/cohere/call_response_chunk.py +0 -125
- mirascope/core/cohere/dynamic_config.py +0 -32
- mirascope/core/cohere/py.typed +0 -0
- mirascope/core/cohere/stream.py +0 -113
- mirascope/core/cohere/tool.py +0 -93
- mirascope/core/costs/__init__.py +0 -5
- mirascope/core/costs/_anthropic_calculate_cost.py +0 -219
- mirascope/core/costs/_azure_calculate_cost.py +0 -11
- mirascope/core/costs/_bedrock_calculate_cost.py +0 -15
- mirascope/core/costs/_cohere_calculate_cost.py +0 -44
- mirascope/core/costs/_gemini_calculate_cost.py +0 -67
- mirascope/core/costs/_google_calculate_cost.py +0 -427
- mirascope/core/costs/_groq_calculate_cost.py +0 -156
- mirascope/core/costs/_litellm_calculate_cost.py +0 -11
- mirascope/core/costs/_mistral_calculate_cost.py +0 -64
- mirascope/core/costs/_openai_calculate_cost.py +0 -416
- mirascope/core/costs/_vertex_calculate_cost.py +0 -67
- mirascope/core/costs/_xai_calculate_cost.py +0 -104
- mirascope/core/costs/calculate_cost.py +0 -86
- mirascope/core/gemini/__init__.py +0 -40
- mirascope/core/gemini/_call.py +0 -67
- mirascope/core/gemini/_call_kwargs.py +0 -12
- mirascope/core/gemini/_utils/__init__.py +0 -14
- mirascope/core/gemini/_utils/_convert_common_call_params.py +0 -39
- mirascope/core/gemini/_utils/_convert_finish_reason_to_common_finish_reasons.py +0 -23
- mirascope/core/gemini/_utils/_convert_message_params.py +0 -156
- mirascope/core/gemini/_utils/_get_json_output.py +0 -35
- mirascope/core/gemini/_utils/_handle_stream.py +0 -33
- mirascope/core/gemini/_utils/_message_param_converter.py +0 -209
- mirascope/core/gemini/_utils/_setup_call.py +0 -149
- mirascope/core/gemini/call_params.py +0 -52
- mirascope/core/gemini/call_response.py +0 -216
- mirascope/core/gemini/call_response_chunk.py +0 -100
- mirascope/core/gemini/dynamic_config.py +0 -26
- mirascope/core/gemini/stream.py +0 -120
- mirascope/core/gemini/tool.py +0 -104
- mirascope/core/google/__init__.py +0 -29
- mirascope/core/google/_call.py +0 -67
- mirascope/core/google/_call_kwargs.py +0 -13
- mirascope/core/google/_utils/__init__.py +0 -14
- mirascope/core/google/_utils/_convert_common_call_params.py +0 -38
- mirascope/core/google/_utils/_convert_finish_reason_to_common_finish_reasons.py +0 -27
- mirascope/core/google/_utils/_convert_message_params.py +0 -297
- mirascope/core/google/_utils/_get_json_output.py +0 -37
- mirascope/core/google/_utils/_handle_stream.py +0 -58
- mirascope/core/google/_utils/_message_param_converter.py +0 -200
- mirascope/core/google/_utils/_setup_call.py +0 -201
- mirascope/core/google/_utils/_validate_media_type.py +0 -58
- mirascope/core/google/call_params.py +0 -22
- mirascope/core/google/call_response.py +0 -255
- mirascope/core/google/call_response_chunk.py +0 -135
- mirascope/core/google/dynamic_config.py +0 -26
- mirascope/core/google/stream.py +0 -199
- mirascope/core/google/tool.py +0 -146
- mirascope/core/groq/__init__.py +0 -30
- mirascope/core/groq/_call.py +0 -67
- mirascope/core/groq/_call_kwargs.py +0 -13
- mirascope/core/groq/_utils/__init__.py +0 -14
- mirascope/core/groq/_utils/_convert_common_call_params.py +0 -26
- mirascope/core/groq/_utils/_convert_message_params.py +0 -112
- mirascope/core/groq/_utils/_get_json_output.py +0 -27
- mirascope/core/groq/_utils/_handle_stream.py +0 -123
- mirascope/core/groq/_utils/_message_param_converter.py +0 -89
- mirascope/core/groq/_utils/_setup_call.py +0 -132
- mirascope/core/groq/call_params.py +0 -52
- mirascope/core/groq/call_response.py +0 -213
- mirascope/core/groq/call_response_chunk.py +0 -104
- mirascope/core/groq/dynamic_config.py +0 -29
- mirascope/core/groq/py.typed +0 -0
- mirascope/core/groq/stream.py +0 -135
- mirascope/core/groq/tool.py +0 -80
- mirascope/core/litellm/__init__.py +0 -28
- mirascope/core/litellm/_call.py +0 -67
- mirascope/core/litellm/_utils/__init__.py +0 -5
- mirascope/core/litellm/_utils/_setup_call.py +0 -109
- mirascope/core/litellm/call_params.py +0 -10
- mirascope/core/litellm/call_response.py +0 -24
- mirascope/core/litellm/call_response_chunk.py +0 -14
- mirascope/core/litellm/dynamic_config.py +0 -8
- mirascope/core/litellm/py.typed +0 -0
- mirascope/core/litellm/stream.py +0 -86
- mirascope/core/litellm/tool.py +0 -13
- mirascope/core/mistral/__init__.py +0 -36
- mirascope/core/mistral/_call.py +0 -65
- mirascope/core/mistral/_call_kwargs.py +0 -19
- mirascope/core/mistral/_utils/__init__.py +0 -14
- mirascope/core/mistral/_utils/_convert_common_call_params.py +0 -24
- mirascope/core/mistral/_utils/_convert_finish_reason_to_common_finish_reasons.py +0 -22
- mirascope/core/mistral/_utils/_convert_message_params.py +0 -122
- mirascope/core/mistral/_utils/_get_json_output.py +0 -34
- mirascope/core/mistral/_utils/_handle_stream.py +0 -139
- mirascope/core/mistral/_utils/_message_param_converter.py +0 -176
- mirascope/core/mistral/_utils/_setup_call.py +0 -164
- mirascope/core/mistral/call_params.py +0 -36
- mirascope/core/mistral/call_response.py +0 -205
- mirascope/core/mistral/call_response_chunk.py +0 -105
- mirascope/core/mistral/dynamic_config.py +0 -33
- mirascope/core/mistral/py.typed +0 -0
- mirascope/core/mistral/stream.py +0 -120
- mirascope/core/mistral/tool.py +0 -81
- mirascope/core/openai/__init__.py +0 -31
- mirascope/core/openai/_call.py +0 -67
- mirascope/core/openai/_call_kwargs.py +0 -13
- mirascope/core/openai/_utils/__init__.py +0 -14
- mirascope/core/openai/_utils/_convert_common_call_params.py +0 -26
- mirascope/core/openai/_utils/_convert_message_params.py +0 -148
- mirascope/core/openai/_utils/_get_json_output.py +0 -31
- mirascope/core/openai/_utils/_handle_stream.py +0 -138
- mirascope/core/openai/_utils/_message_param_converter.py +0 -105
- mirascope/core/openai/_utils/_setup_call.py +0 -155
- mirascope/core/openai/call_params.py +0 -92
- mirascope/core/openai/call_response.py +0 -273
- mirascope/core/openai/call_response_chunk.py +0 -139
- mirascope/core/openai/dynamic_config.py +0 -34
- mirascope/core/openai/py.typed +0 -0
- mirascope/core/openai/stream.py +0 -185
- mirascope/core/openai/tool.py +0 -101
- mirascope/core/py.typed +0 -0
- mirascope/core/vertex/__init__.py +0 -45
- mirascope/core/vertex/_call.py +0 -62
- mirascope/core/vertex/_call_kwargs.py +0 -12
- mirascope/core/vertex/_utils/__init__.py +0 -14
- mirascope/core/vertex/_utils/_convert_common_call_params.py +0 -37
- mirascope/core/vertex/_utils/_convert_finish_reason_to_common_finish_reasons.py +0 -23
- mirascope/core/vertex/_utils/_convert_message_params.py +0 -171
- mirascope/core/vertex/_utils/_get_json_output.py +0 -36
- mirascope/core/vertex/_utils/_handle_stream.py +0 -33
- mirascope/core/vertex/_utils/_message_param_converter.py +0 -133
- mirascope/core/vertex/_utils/_setup_call.py +0 -160
- mirascope/core/vertex/call_params.py +0 -24
- mirascope/core/vertex/call_response.py +0 -206
- mirascope/core/vertex/call_response_chunk.py +0 -99
- mirascope/core/vertex/dynamic_config.py +0 -28
- mirascope/core/vertex/stream.py +0 -119
- mirascope/core/vertex/tool.py +0 -101
- mirascope/core/xai/__init__.py +0 -28
- mirascope/core/xai/_call.py +0 -67
- mirascope/core/xai/_utils/__init__.py +0 -5
- mirascope/core/xai/_utils/_setup_call.py +0 -113
- mirascope/core/xai/call_params.py +0 -10
- mirascope/core/xai/call_response.py +0 -16
- mirascope/core/xai/call_response_chunk.py +0 -14
- mirascope/core/xai/dynamic_config.py +0 -8
- mirascope/core/xai/py.typed +0 -0
- mirascope/core/xai/stream.py +0 -57
- mirascope/core/xai/tool.py +0 -13
- mirascope/experimental/graphs/__init__.py +0 -5
- mirascope/integrations/__init__.py +0 -16
- mirascope/integrations/_middleware_factory.py +0 -403
- mirascope/integrations/langfuse/__init__.py +0 -3
- mirascope/integrations/langfuse/_utils.py +0 -114
- mirascope/integrations/langfuse/_with_langfuse.py +0 -70
- mirascope/integrations/logfire/__init__.py +0 -3
- mirascope/integrations/logfire/_utils.py +0 -225
- mirascope/integrations/logfire/_with_logfire.py +0 -63
- mirascope/integrations/otel/__init__.py +0 -10
- mirascope/integrations/otel/_utils.py +0 -270
- mirascope/integrations/otel/_with_hyperdx.py +0 -60
- mirascope/integrations/otel/_with_otel.py +0 -59
- mirascope/integrations/tenacity.py +0 -14
- mirascope/llm/_call.py +0 -401
- mirascope/llm/_context.py +0 -384
- mirascope/llm/_override.py +0 -3639
- mirascope/llm/_protocols.py +0 -500
- mirascope/llm/_response_metaclass.py +0 -31
- mirascope/llm/call_response.py +0 -158
- mirascope/llm/call_response_chunk.py +0 -66
- mirascope/llm/stream.py +0 -162
- mirascope/llm/tool.py +0 -64
- mirascope/mcp/__init__.py +0 -7
- mirascope/mcp/_utils.py +0 -288
- mirascope/mcp/client.py +0 -167
- mirascope/mcp/server.py +0 -356
- mirascope/mcp/tools.py +0 -110
- mirascope/py.typed +0 -0
- mirascope/retries/__init__.py +0 -11
- mirascope/retries/fallback.py +0 -131
- mirascope/retries/tenacity.py +0 -50
- mirascope/tools/__init__.py +0 -37
- mirascope/tools/base.py +0 -98
- mirascope/tools/system/__init__.py +0 -0
- mirascope/tools/system/_docker_operation.py +0 -166
- mirascope/tools/system/_file_system.py +0 -267
- mirascope/tools/web/__init__.py +0 -0
- mirascope/tools/web/_duckduckgo.py +0 -111
- mirascope/tools/web/_httpx.py +0 -125
- mirascope/tools/web/_parse_url_content.py +0 -94
- mirascope/tools/web/_requests.py +0 -54
- mirascope/v0/__init__.py +0 -43
- mirascope/v0/anthropic.py +0 -54
- mirascope/v0/base/__init__.py +0 -12
- mirascope/v0/base/calls.py +0 -118
- mirascope/v0/base/extractors.py +0 -122
- mirascope/v0/base/ops_utils.py +0 -207
- mirascope/v0/base/prompts.py +0 -48
- mirascope/v0/base/types.py +0 -14
- mirascope/v0/base/utils.py +0 -21
- mirascope/v0/openai.py +0 -54
- mirascope-1.25.7.dist-info/METADATA +0 -169
- mirascope-1.25.7.dist-info/RECORD +0 -378
- {mirascope-1.25.7.dist-info → mirascope-2.0.0a0.dist-info}/WHEEL +0 -0
- {mirascope-1.25.7.dist-info → mirascope-2.0.0a0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Shared utils for all OpenAI clients."""
|
|
2
|
+
|
|
3
|
+
MODELS_WITHOUT_JSON_SCHEMA_SUPPORT = {
|
|
4
|
+
"chatgpt-4o-latest",
|
|
5
|
+
"gpt-3.5-turbo",
|
|
6
|
+
"gpt-3.5-turbo-0125",
|
|
7
|
+
"gpt-3.5-turbo-1106",
|
|
8
|
+
"gpt-3.5-turbo-16k",
|
|
9
|
+
"gpt-4",
|
|
10
|
+
"gpt-4-0125-preview",
|
|
11
|
+
"gpt-4-0613",
|
|
12
|
+
"gpt-4-1106-preview",
|
|
13
|
+
"gpt-4-turbo",
|
|
14
|
+
"gpt-4-turbo-2024-04-09",
|
|
15
|
+
"gpt-4-turbo-preview",
|
|
16
|
+
"gpt-4o-2024-05-13",
|
|
17
|
+
"gpt-4o-audio-preview",
|
|
18
|
+
"gpt-4o-audio-preview-2024-10-01",
|
|
19
|
+
"gpt-4o-audio-preview-2024-12-17",
|
|
20
|
+
"gpt-4o-audio-preview-2025-06-03",
|
|
21
|
+
"gpt-4o-mini-audio-preview",
|
|
22
|
+
"gpt-4o-mini-audio-preview-2024-12-17",
|
|
23
|
+
"gpt-5-chat-latest",
|
|
24
|
+
"o1-mini",
|
|
25
|
+
"o1-mini-2024-09-12",
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
MODELS_WITHOUT_JSON_OBJECT_SUPPORT = {
|
|
29
|
+
"gpt-4",
|
|
30
|
+
"gpt-4-0613",
|
|
31
|
+
"gpt-4o-audio-preview",
|
|
32
|
+
"gpt-4o-audio-preview-2024-10-01",
|
|
33
|
+
"gpt-4o-audio-preview-2024-12-17",
|
|
34
|
+
"gpt-4o-audio-preview-2025-06-03",
|
|
35
|
+
"gpt-4o-mini-audio-preview",
|
|
36
|
+
"gpt-4o-mini-audio-preview-2024-12-17",
|
|
37
|
+
"gpt-4o-mini-search-preview",
|
|
38
|
+
"gpt-4o-mini-search-preview-2025-03-11",
|
|
39
|
+
"gpt-4o-search-preview",
|
|
40
|
+
"gpt-4o-search-preview-2025-03-11",
|
|
41
|
+
"o1-mini",
|
|
42
|
+
"o1-mini-2024-09-12",
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _ensure_additional_properties_false(obj: object) -> None:
|
|
47
|
+
"""Recursively adds additionalProperties = False to a schema, required by OpenAI API."""
|
|
48
|
+
if isinstance(obj, dict):
|
|
49
|
+
if obj.get("type") == "object" and "additionalProperties" not in obj:
|
|
50
|
+
obj["additionalProperties"] = False
|
|
51
|
+
for value in obj.values():
|
|
52
|
+
_ensure_additional_properties_false(value)
|
|
53
|
+
elif isinstance(obj, list):
|
|
54
|
+
for item in obj:
|
|
55
|
+
_ensure_additional_properties_false(item)
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
from typing import Literal, TypeAlias, get_args, overload
|
|
2
|
+
|
|
3
|
+
from .anthropic import (
|
|
4
|
+
AnthropicClient,
|
|
5
|
+
AnthropicModelId,
|
|
6
|
+
client as anthropic_client,
|
|
7
|
+
get_client as get_anthropic_client,
|
|
8
|
+
)
|
|
9
|
+
from .google import (
|
|
10
|
+
GoogleClient,
|
|
11
|
+
GoogleModelId,
|
|
12
|
+
client as google_client,
|
|
13
|
+
get_client as get_google_client,
|
|
14
|
+
)
|
|
15
|
+
from .openai import (
|
|
16
|
+
OpenAICompletionsClient,
|
|
17
|
+
OpenAICompletionsModelId,
|
|
18
|
+
OpenAIResponsesClient,
|
|
19
|
+
OpenAIResponsesModelId,
|
|
20
|
+
completions_client as openai_completions_client,
|
|
21
|
+
get_completions_client as get_openai_completions_client,
|
|
22
|
+
get_responses_client as get_openai_responses_client,
|
|
23
|
+
responses_client as openai_responses_client,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
Provider: TypeAlias = Literal[
|
|
27
|
+
"anthropic",
|
|
28
|
+
"google",
|
|
29
|
+
"openai:completions", # OpenAICompletionsClient
|
|
30
|
+
"openai:responses", # OpenAIResponsesClient
|
|
31
|
+
"openai", # Alias for "openai:responses"
|
|
32
|
+
]
|
|
33
|
+
PROVIDERS = get_args(Provider)
|
|
34
|
+
|
|
35
|
+
ModelId: TypeAlias = (
|
|
36
|
+
AnthropicModelId
|
|
37
|
+
| GoogleModelId
|
|
38
|
+
| OpenAIResponsesModelId
|
|
39
|
+
| OpenAICompletionsModelId
|
|
40
|
+
| str
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@overload
|
|
45
|
+
def get_client(provider: Literal["anthropic"]) -> AnthropicClient:
|
|
46
|
+
"""Get an Anthropic client instance."""
|
|
47
|
+
...
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@overload
|
|
51
|
+
def get_client(provider: Literal["google"]) -> GoogleClient:
|
|
52
|
+
"""Get a Google client instance."""
|
|
53
|
+
...
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@overload
|
|
57
|
+
def get_client(provider: Literal["openai:completions"]) -> OpenAICompletionsClient:
|
|
58
|
+
"""Get an OpenAI client instance."""
|
|
59
|
+
...
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@overload
|
|
63
|
+
def get_client(
|
|
64
|
+
provider: Literal["openai:responses", "openai"],
|
|
65
|
+
) -> OpenAIResponsesClient:
|
|
66
|
+
"""Get an OpenAI responses client instance."""
|
|
67
|
+
...
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def get_client(
|
|
71
|
+
provider: Provider,
|
|
72
|
+
) -> AnthropicClient | GoogleClient | OpenAICompletionsClient | OpenAIResponsesClient:
|
|
73
|
+
"""Get a client instance for the specified provider.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
provider: The provider name ("openai:completions", "anthropic", or "google").
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
A client instance for the specified provider. The specific client type
|
|
80
|
+
depends on the provider:
|
|
81
|
+
- "openai:completions" returns `OpenAICompletionsClient` (ChatCompletion API)
|
|
82
|
+
- "openai:responses" returns `OpenAIResponsesClient` (Responses API)
|
|
83
|
+
- "anthropic" returns `AnthropicClient`
|
|
84
|
+
- "google" returns `GoogleClient`
|
|
85
|
+
|
|
86
|
+
Multiple calls to get_client will return the same Client rather than constructing
|
|
87
|
+
new ones.
|
|
88
|
+
|
|
89
|
+
Raises:
|
|
90
|
+
ValueError: If the provider is not supported.
|
|
91
|
+
"""
|
|
92
|
+
match provider:
|
|
93
|
+
case "anthropic":
|
|
94
|
+
return get_anthropic_client()
|
|
95
|
+
case "google":
|
|
96
|
+
return get_google_client()
|
|
97
|
+
case "openai:completions":
|
|
98
|
+
return get_openai_completions_client()
|
|
99
|
+
case "openai:responses" | "openai":
|
|
100
|
+
return get_openai_responses_client()
|
|
101
|
+
case _:
|
|
102
|
+
raise ValueError(f"Unknown provider: {provider}")
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@overload
|
|
106
|
+
def client(
|
|
107
|
+
provider: Literal["openai:completions"],
|
|
108
|
+
*,
|
|
109
|
+
api_key: str | None = None,
|
|
110
|
+
base_url: str | None = None,
|
|
111
|
+
) -> OpenAICompletionsClient:
|
|
112
|
+
"""Create a cached OpenAI chat completions client with the given parameters."""
|
|
113
|
+
...
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@overload
|
|
117
|
+
def client(
|
|
118
|
+
provider: Literal["openai:responses", "openai"],
|
|
119
|
+
*,
|
|
120
|
+
api_key: str | None = None,
|
|
121
|
+
base_url: str | None = None,
|
|
122
|
+
) -> OpenAIResponsesClient:
|
|
123
|
+
"""Create a cached OpenAI responses client with the given parameters."""
|
|
124
|
+
...
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@overload
|
|
128
|
+
def client(
|
|
129
|
+
provider: Literal["anthropic"],
|
|
130
|
+
*,
|
|
131
|
+
api_key: str | None = None,
|
|
132
|
+
base_url: str | None = None,
|
|
133
|
+
) -> AnthropicClient:
|
|
134
|
+
"""Create a cached Anthropic client with the given parameters."""
|
|
135
|
+
...
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
@overload
|
|
139
|
+
def client(
|
|
140
|
+
provider: Literal["google"],
|
|
141
|
+
*,
|
|
142
|
+
api_key: str | None = None,
|
|
143
|
+
base_url: str | None = None,
|
|
144
|
+
) -> GoogleClient:
|
|
145
|
+
"""Create a cached Google client with the given parameters."""
|
|
146
|
+
...
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def client(
|
|
150
|
+
provider: Provider, *, api_key: str | None = None, base_url: str | None = None
|
|
151
|
+
) -> AnthropicClient | GoogleClient | OpenAICompletionsClient | OpenAIResponsesClient:
|
|
152
|
+
"""Create a cached client instance for the specified provider.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
provider: The provider name ("openai:completions", "anthropic", or "google").
|
|
156
|
+
api_key: API key for authentication. If None, uses provider-specific env var.
|
|
157
|
+
base_url: Base URL for the API. If None, uses provider-specific env var.
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
A cached client instance for the specified provider with the given parameters.
|
|
161
|
+
|
|
162
|
+
Raises:
|
|
163
|
+
ValueError: If the provider is not supported.
|
|
164
|
+
"""
|
|
165
|
+
match provider:
|
|
166
|
+
case "anthropic":
|
|
167
|
+
return anthropic_client(api_key=api_key, base_url=base_url)
|
|
168
|
+
case "google":
|
|
169
|
+
return google_client(api_key=api_key, base_url=base_url)
|
|
170
|
+
case "openai:completions":
|
|
171
|
+
return openai_completions_client(api_key=api_key, base_url=base_url)
|
|
172
|
+
case "openai:responses" | "openai":
|
|
173
|
+
return openai_responses_client(api_key=api_key, base_url=base_url)
|
|
174
|
+
case _: # pragma: no cover
|
|
175
|
+
raise ValueError(f"Unknown provider: {provider}")
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""The `llm.messages.content` module."""
|
|
2
|
+
|
|
3
|
+
from typing import TypeAlias
|
|
4
|
+
|
|
5
|
+
from .audio import Audio, Base64AudioSource
|
|
6
|
+
from .document import (
|
|
7
|
+
Base64DocumentSource,
|
|
8
|
+
Document,
|
|
9
|
+
TextDocumentSource,
|
|
10
|
+
URLDocumentSource,
|
|
11
|
+
)
|
|
12
|
+
from .image import Base64ImageSource, Image, ImageMimeType, URLImageSource
|
|
13
|
+
from .text import Text, TextChunk, TextEndChunk, TextStartChunk
|
|
14
|
+
from .thought import Thought, ThoughtChunk, ThoughtEndChunk, ThoughtStartChunk
|
|
15
|
+
from .tool_call import ToolCall, ToolCallChunk, ToolCallEndChunk, ToolCallStartChunk
|
|
16
|
+
from .tool_output import ToolOutput
|
|
17
|
+
|
|
18
|
+
ContentPart: TypeAlias = (
|
|
19
|
+
Text | Image | Audio | Document | ToolOutput | ToolCall | Thought
|
|
20
|
+
)
|
|
21
|
+
"""Content parts that may be included in a Message."""
|
|
22
|
+
|
|
23
|
+
UserContentPart: TypeAlias = Text | Image | Audio | Document | ToolOutput
|
|
24
|
+
"""Content parts that can be included in a UserMessage."""
|
|
25
|
+
|
|
26
|
+
AssistantContentPart: TypeAlias = Text | ToolCall | Thought
|
|
27
|
+
"""Content parts that can be included in an AssistantMessage."""
|
|
28
|
+
|
|
29
|
+
AssistantContentChunk: TypeAlias = (
|
|
30
|
+
TextStartChunk
|
|
31
|
+
| TextChunk
|
|
32
|
+
| TextEndChunk
|
|
33
|
+
| ThoughtStartChunk
|
|
34
|
+
| ThoughtChunk
|
|
35
|
+
| ThoughtEndChunk
|
|
36
|
+
| ToolCallStartChunk
|
|
37
|
+
| ToolCallChunk
|
|
38
|
+
| ToolCallEndChunk
|
|
39
|
+
)
|
|
40
|
+
"""Chunks of assistant content that may be streamed as generated by the LLM."""
|
|
41
|
+
|
|
42
|
+
__all__ = [
|
|
43
|
+
"AssistantContentChunk",
|
|
44
|
+
"AssistantContentPart",
|
|
45
|
+
"Audio",
|
|
46
|
+
"Base64AudioSource",
|
|
47
|
+
"Base64DocumentSource",
|
|
48
|
+
"Base64ImageSource",
|
|
49
|
+
"ContentPart",
|
|
50
|
+
"Document",
|
|
51
|
+
"Image",
|
|
52
|
+
"ImageMimeType",
|
|
53
|
+
"Text",
|
|
54
|
+
"TextChunk",
|
|
55
|
+
"TextDocumentSource",
|
|
56
|
+
"TextEndChunk",
|
|
57
|
+
"TextStartChunk",
|
|
58
|
+
"Thought",
|
|
59
|
+
"ThoughtChunk",
|
|
60
|
+
"ThoughtEndChunk",
|
|
61
|
+
"ThoughtStartChunk",
|
|
62
|
+
"ToolCall",
|
|
63
|
+
"ToolCallChunk",
|
|
64
|
+
"ToolCallEndChunk",
|
|
65
|
+
"ToolCallStartChunk",
|
|
66
|
+
"ToolOutput",
|
|
67
|
+
"URLDocumentSource",
|
|
68
|
+
"URLImageSource",
|
|
69
|
+
"UserContentPart",
|
|
70
|
+
]
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"""The `Audio` content class."""
|
|
2
|
+
|
|
3
|
+
import base64
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Literal, get_args
|
|
7
|
+
|
|
8
|
+
import httpx
|
|
9
|
+
|
|
10
|
+
AudioMimeType = Literal[
|
|
11
|
+
"audio/wav",
|
|
12
|
+
"audio/mp3",
|
|
13
|
+
"audio/aiff",
|
|
14
|
+
"audio/aac",
|
|
15
|
+
"audio/ogg",
|
|
16
|
+
"audio/flac",
|
|
17
|
+
] # TODO: add e2e tests for every supported type
|
|
18
|
+
|
|
19
|
+
MIME_TYPES = get_args(AudioMimeType)
|
|
20
|
+
|
|
21
|
+
# Maximum audio size in bytes (25MB)
|
|
22
|
+
MAX_AUDIO_SIZE = 25 * 1024 * 1024
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def infer_audio_type(audio_data: bytes) -> AudioMimeType:
|
|
26
|
+
"""Get the MIME type of an audio file from its raw bytes.
|
|
27
|
+
|
|
28
|
+
Raises:
|
|
29
|
+
ValueError: If the audio type cannot be determined or data is too small
|
|
30
|
+
"""
|
|
31
|
+
if len(audio_data) < 12:
|
|
32
|
+
raise ValueError("Audio data too small to determine type (minimum 12 bytes)")
|
|
33
|
+
|
|
34
|
+
if audio_data.startswith(b"RIFF") and audio_data[8:12] == b"WAVE":
|
|
35
|
+
return "audio/wav"
|
|
36
|
+
elif audio_data.startswith(b"ID3") or audio_data.startswith(b"\xff\xfb"):
|
|
37
|
+
return "audio/mp3"
|
|
38
|
+
elif audio_data.startswith(b"FORM") and audio_data[8:12] == b"AIFF":
|
|
39
|
+
return "audio/aiff"
|
|
40
|
+
elif audio_data.startswith(b"\xff\xf1") or audio_data.startswith(b"\xff\xf9"):
|
|
41
|
+
return "audio/aac"
|
|
42
|
+
elif audio_data.startswith(b"OggS"):
|
|
43
|
+
return "audio/ogg"
|
|
44
|
+
elif audio_data.startswith(b"fLaC"):
|
|
45
|
+
return "audio/flac"
|
|
46
|
+
raise ValueError("Unsupported audio type")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass(kw_only=True)
|
|
50
|
+
class Base64AudioSource:
|
|
51
|
+
"""Audio data represented as a base64 encoded string."""
|
|
52
|
+
|
|
53
|
+
type: Literal["base64_audio_source"]
|
|
54
|
+
|
|
55
|
+
data: str
|
|
56
|
+
"""The audio data, as a base64 encoded string."""
|
|
57
|
+
|
|
58
|
+
mime_type: AudioMimeType
|
|
59
|
+
"""The mime type of the audio (e.g. audio/mp3)."""
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _process_audio_bytes(data: bytes, max_size: int) -> Base64AudioSource:
|
|
63
|
+
"""Validate and process audio bytes into a Base64AudioSource.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
data: Raw audio bytes
|
|
67
|
+
max_size: Maximum allowed size in bytes
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
A Base64AudioSource with validated and encoded data
|
|
71
|
+
|
|
72
|
+
Raises:
|
|
73
|
+
ValueError: If data size exceeds max_size
|
|
74
|
+
"""
|
|
75
|
+
size = len(data)
|
|
76
|
+
if size > max_size:
|
|
77
|
+
raise ValueError(
|
|
78
|
+
f"Audio size ({size} bytes) exceeds maximum allowed size ({max_size} bytes)"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
mime_type = infer_audio_type(data)
|
|
82
|
+
encoded_data = base64.b64encode(data).decode("utf-8")
|
|
83
|
+
return Base64AudioSource(
|
|
84
|
+
type="base64_audio_source",
|
|
85
|
+
data=encoded_data,
|
|
86
|
+
mime_type=mime_type,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@dataclass(kw_only=True)
|
|
91
|
+
class Audio:
|
|
92
|
+
"""Audio content for a message.
|
|
93
|
+
|
|
94
|
+
Audio can be included in messages for voice or sound-based interactions.
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
type: Literal["audio"] = "audio"
|
|
98
|
+
|
|
99
|
+
source: Base64AudioSource
|
|
100
|
+
|
|
101
|
+
@classmethod
|
|
102
|
+
def download(cls, url: str, *, max_size: int = MAX_AUDIO_SIZE) -> "Audio":
|
|
103
|
+
"""Download and encode an audio file from a URL.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
url: The URL of the audio file to download
|
|
107
|
+
max_size: Maximum allowed audio size in bytes (default: 25MB)
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
An `Audio` with a `Base64AudioSource`
|
|
111
|
+
|
|
112
|
+
Raises:
|
|
113
|
+
ValueError: If the downloaded audio exceeds max_size
|
|
114
|
+
"""
|
|
115
|
+
response = httpx.get(url, follow_redirects=True)
|
|
116
|
+
response.raise_for_status()
|
|
117
|
+
return cls(source=_process_audio_bytes(response.content, max_size))
|
|
118
|
+
|
|
119
|
+
@classmethod
|
|
120
|
+
async def download_async(
|
|
121
|
+
cls, url: str, *, max_size: int = MAX_AUDIO_SIZE
|
|
122
|
+
) -> "Audio":
|
|
123
|
+
"""Asynchronously download and encode an audio file from a URL.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
url: The URL of the audio file to download
|
|
127
|
+
max_size: Maximum allowed audio size in bytes (default: 25MB)
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
An `Audio` with a `Base64AudioSource`
|
|
131
|
+
|
|
132
|
+
Raises:
|
|
133
|
+
ValueError: If the downloaded audio exceeds max_size
|
|
134
|
+
"""
|
|
135
|
+
async with httpx.AsyncClient() as client:
|
|
136
|
+
response = await client.get(url, follow_redirects=True)
|
|
137
|
+
response.raise_for_status()
|
|
138
|
+
return cls(source=_process_audio_bytes(response.content, max_size))
|
|
139
|
+
|
|
140
|
+
@classmethod
|
|
141
|
+
def from_file(cls, file_path: str, *, max_size: int = MAX_AUDIO_SIZE) -> "Audio":
|
|
142
|
+
"""Create an `Audio` from a file path.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
file_path: Path to the audio file
|
|
146
|
+
max_size: Maximum allowed audio size in bytes (default: 25MB)
|
|
147
|
+
|
|
148
|
+
Raises:
|
|
149
|
+
FileNotFoundError: If the file does not exist
|
|
150
|
+
ValueError: If the file size exceeds max_size
|
|
151
|
+
"""
|
|
152
|
+
path = Path(file_path)
|
|
153
|
+
file_size = path.stat().st_size
|
|
154
|
+
if file_size > max_size:
|
|
155
|
+
raise ValueError(
|
|
156
|
+
f"Audio file size ({file_size} bytes) exceeds maximum allowed size ({max_size} bytes)"
|
|
157
|
+
)
|
|
158
|
+
with open(path, "rb") as f:
|
|
159
|
+
audio_bytes = f.read()
|
|
160
|
+
return cls(source=_process_audio_bytes(audio_bytes, max_size))
|
|
161
|
+
|
|
162
|
+
@classmethod
|
|
163
|
+
def from_bytes(cls, data: bytes, *, max_size: int = MAX_AUDIO_SIZE) -> "Audio":
|
|
164
|
+
"""Create an `Audio` from raw bytes.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
data: Raw audio bytes
|
|
168
|
+
max_size: Maximum allowed audio size in bytes (default: 25MB)
|
|
169
|
+
|
|
170
|
+
Raises:
|
|
171
|
+
ValueError: If the data size exceeds max_size
|
|
172
|
+
"""
|
|
173
|
+
return cls(source=_process_audio_bytes(data, max_size))
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""The `Document` content class."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
6
|
+
DocumentTextMimeType = Literal[
|
|
7
|
+
"application/json",
|
|
8
|
+
"text/plain",
|
|
9
|
+
"application/x-javascript",
|
|
10
|
+
"text/javascript",
|
|
11
|
+
"application/x-python",
|
|
12
|
+
"text/x-python",
|
|
13
|
+
"text/html",
|
|
14
|
+
"text/css",
|
|
15
|
+
"text/xml",
|
|
16
|
+
"text/rtf",
|
|
17
|
+
]
|
|
18
|
+
"""Mime type for documents encoded as plain text."""
|
|
19
|
+
|
|
20
|
+
DocumentBase64MimeType = Literal["application/pdf"]
|
|
21
|
+
"""Mime type for documents encoded as base64 strings."""
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(kw_only=True)
|
|
25
|
+
class Base64DocumentSource:
|
|
26
|
+
"""Document data represented as a base64 encoded string."""
|
|
27
|
+
|
|
28
|
+
type: Literal["base64_document_source"]
|
|
29
|
+
|
|
30
|
+
data: str
|
|
31
|
+
"""The document data, as a base64 encoded string."""
|
|
32
|
+
|
|
33
|
+
media_type: DocumentBase64MimeType
|
|
34
|
+
"""The media type of the document (e.g. application/pdf)."""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass(kw_only=True)
|
|
38
|
+
class TextDocumentSource:
|
|
39
|
+
"""Plain text document data."""
|
|
40
|
+
|
|
41
|
+
type: Literal["text_document_source"]
|
|
42
|
+
|
|
43
|
+
data: str
|
|
44
|
+
"""The document data, as plain text."""
|
|
45
|
+
|
|
46
|
+
media_type: DocumentTextMimeType
|
|
47
|
+
"""The media type of the document (e.g. text/plain, text/csv)."""
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass(kw_only=True)
|
|
51
|
+
class URLDocumentSource:
|
|
52
|
+
"""Document data referenced via external URL."""
|
|
53
|
+
|
|
54
|
+
type: Literal["url_document_source"]
|
|
55
|
+
|
|
56
|
+
url: str
|
|
57
|
+
"""The url of the document (e.g. https://example.com/paper.pdf)."""
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@dataclass(kw_only=True)
|
|
61
|
+
class Document:
|
|
62
|
+
"""Document content for a message.
|
|
63
|
+
|
|
64
|
+
Documents (like PDFs) can be included for the model to analyze or reference.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
type: Literal["document"] = "document"
|
|
68
|
+
|
|
69
|
+
source: Base64DocumentSource | TextDocumentSource | URLDocumentSource
|
|
70
|
+
|
|
71
|
+
@classmethod
|
|
72
|
+
def from_url(cls, url: str, *, download: bool = False) -> "Document":
|
|
73
|
+
"""Create a `Document` from a URL."""
|
|
74
|
+
raise NotImplementedError
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def from_file(
|
|
78
|
+
cls,
|
|
79
|
+
file_path: str,
|
|
80
|
+
*,
|
|
81
|
+
mime_type: DocumentTextMimeType | DocumentBase64MimeType | None,
|
|
82
|
+
) -> "Document":
|
|
83
|
+
"""Create a `Document` from a file path."""
|
|
84
|
+
raise NotImplementedError
|
|
85
|
+
|
|
86
|
+
@classmethod
|
|
87
|
+
def from_bytes(
|
|
88
|
+
cls,
|
|
89
|
+
data: bytes,
|
|
90
|
+
*,
|
|
91
|
+
mime_type: DocumentTextMimeType | DocumentBase64MimeType | None,
|
|
92
|
+
) -> "Document":
|
|
93
|
+
"""Create a `Document` from raw bytes."""
|
|
94
|
+
raise NotImplementedError
|