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,104 @@
|
|
|
1
|
+
"""The `llm.format` decorator for defining response formats as classes."""
|
|
2
|
+
|
|
3
|
+
import inspect
|
|
4
|
+
|
|
5
|
+
from ..types import NoneType
|
|
6
|
+
from ._utils import default_formatting_instructions
|
|
7
|
+
from .types import Format, FormattableT, FormattingMode, HasFormattingInstructions
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def format(
|
|
11
|
+
formattable: type[FormattableT] | None,
|
|
12
|
+
*,
|
|
13
|
+
mode: FormattingMode,
|
|
14
|
+
) -> Format[FormattableT] | None:
|
|
15
|
+
"""Returns a `Format` that describes structured output for a Formattable type.
|
|
16
|
+
|
|
17
|
+
This function converts a Formattable type (e.g. Pydantic BaseModel) into a `Format`
|
|
18
|
+
object that describes how the object should be formatted. Calling `llm.format`
|
|
19
|
+
is optional, as all the APIs that expect a `Format` can also take the Formattable
|
|
20
|
+
type directly. However, calling `llm.format` is necessary in order to specify the
|
|
21
|
+
formatting mode that will be used.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
mode: The format mode to use, one of the following:
|
|
25
|
+
- "strict": Use model strict structured outputs, or fail if unavailable.
|
|
26
|
+
- "tool": Use forced tool calling with a special tool that represents a
|
|
27
|
+
formatted response.
|
|
28
|
+
- "json": Use provider json mode if available, or modify prompt to request
|
|
29
|
+
json if not.
|
|
30
|
+
|
|
31
|
+
The Formattable type may provide custom formatting instructions via a
|
|
32
|
+
`formatting_instructions(cls)` classmethod. If that method is present, it will be called,
|
|
33
|
+
and the resulting instructions will automatically be appended to the system prompt.
|
|
34
|
+
|
|
35
|
+
If no formatting instructions are present, then Mirascope may auto-generate instructions
|
|
36
|
+
based on the active format mode. To disable this behavior and all prompt modification,
|
|
37
|
+
you can add the `formatting_instructions` classmethod and have it return `None`.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
A `Format` object describing the Formattable type.
|
|
41
|
+
|
|
42
|
+
Example:
|
|
43
|
+
Using with an LLM call:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from pydantic import BaseModel
|
|
47
|
+
|
|
48
|
+
from mirascope import llm
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class Book(BaseModel):
|
|
52
|
+
title: str
|
|
53
|
+
author: str
|
|
54
|
+
|
|
55
|
+
format = llm.format(Book, mode="strict")
|
|
56
|
+
|
|
57
|
+
@llm.call(
|
|
58
|
+
provider="openai:completions",
|
|
59
|
+
model_id="gpt-4o-mini",
|
|
60
|
+
format=format,
|
|
61
|
+
)
|
|
62
|
+
def recommend_book(genre: str):
|
|
63
|
+
return f"Recommend a {genre} book."
|
|
64
|
+
|
|
65
|
+
response = recommend_book("fantasy")
|
|
66
|
+
book: Book = response.parse()
|
|
67
|
+
print(f"{book.title} by {book.author}")
|
|
68
|
+
```
|
|
69
|
+
"""
|
|
70
|
+
# TODO: Add caching or memoization to this function (e.g. functools.lru_cache)
|
|
71
|
+
|
|
72
|
+
if formattable is None or formattable is NoneType:
|
|
73
|
+
return None
|
|
74
|
+
|
|
75
|
+
description = None
|
|
76
|
+
if formattable.__doc__:
|
|
77
|
+
description = inspect.cleandoc(formattable.__doc__)
|
|
78
|
+
|
|
79
|
+
schema = formattable.model_json_schema()
|
|
80
|
+
formatting_instructions = None
|
|
81
|
+
if isinstance(formattable, HasFormattingInstructions):
|
|
82
|
+
formatting_instructions = formattable.formatting_instructions()
|
|
83
|
+
else:
|
|
84
|
+
formatting_instructions = default_formatting_instructions(schema, mode)
|
|
85
|
+
|
|
86
|
+
return Format[FormattableT](
|
|
87
|
+
name=formattable.__name__,
|
|
88
|
+
description=description,
|
|
89
|
+
schema=schema,
|
|
90
|
+
mode=mode,
|
|
91
|
+
formatting_instructions=formatting_instructions,
|
|
92
|
+
formattable=formattable,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def resolve_format(
|
|
97
|
+
formattable: type[FormattableT] | Format[FormattableT] | None,
|
|
98
|
+
default_mode: FormattingMode,
|
|
99
|
+
) -> Format[FormattableT] | None:
|
|
100
|
+
"""Resolve a `Format` (or None) from a possible `Format` or Formattable."""
|
|
101
|
+
if isinstance(formattable, Format):
|
|
102
|
+
return formattable
|
|
103
|
+
else:
|
|
104
|
+
return format(formattable, mode=default_mode)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""The `FromCallArgs` class annotation for marking a field as a call argument."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class FromCallArgs:
|
|
5
|
+
"""A marker class for indicating that a field is a call argument.
|
|
6
|
+
|
|
7
|
+
This ensures that the LLM call does not attempt to generate this field. Instead, it
|
|
8
|
+
will populate this field with the call argument with a matching name.
|
|
9
|
+
|
|
10
|
+
This is useful for colocating e.g. validation of a generated output against and
|
|
11
|
+
input argument (such as the length of an output given a number input).
|
|
12
|
+
|
|
13
|
+
Example:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
class Book(BaseModel):
|
|
17
|
+
title: Annotated[str, llm.formatting.FromCallArgs()]
|
|
18
|
+
author: Annotated[str, llm.formatting.FromCallArgs()]
|
|
19
|
+
summary: str
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@llm.call(
|
|
23
|
+
provider="openai:completions",
|
|
24
|
+
model_id="gpt-4o-mini",
|
|
25
|
+
format=Book,
|
|
26
|
+
)
|
|
27
|
+
def summarize_book(title: str, author: str):
|
|
28
|
+
return f"Summarize {title} by {author}."
|
|
29
|
+
```
|
|
30
|
+
"""
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""
|
|
2
|
+
--------------------------------------------------------------------------------
|
|
3
|
+
Source: https://github.com/pydantic/pydantic/issues/6381#issuecomment-1831607091
|
|
4
|
+
By: silviumarcu
|
|
5
|
+
|
|
6
|
+
This code is used in accordance with the repository's license, and this reference
|
|
7
|
+
serves as an acknowledgment of the original author's contribution to this project.
|
|
8
|
+
--------------------------------------------------------------------------------
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from typing import Generic, NoReturn
|
|
12
|
+
|
|
13
|
+
from .format import FormattableT
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Partial(Generic[FormattableT]):
|
|
17
|
+
"""Generate a new class with all attributes optionals.
|
|
18
|
+
|
|
19
|
+
Notes:
|
|
20
|
+
This will wrap a class inheriting form BaseModel and will recursively
|
|
21
|
+
convert all its attributes and its children's attributes to optionals.
|
|
22
|
+
|
|
23
|
+
Example:
|
|
24
|
+
Partial[SomeModel]
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __new__(
|
|
28
|
+
cls,
|
|
29
|
+
*args: object, # noqa :ARG003
|
|
30
|
+
**kwargs: object, # noqa :ARG003
|
|
31
|
+
) -> "Partial[FormattableT]":
|
|
32
|
+
"""Cannot instantiate.
|
|
33
|
+
|
|
34
|
+
Raises:
|
|
35
|
+
TypeError: Direct instantiation not allowed.
|
|
36
|
+
"""
|
|
37
|
+
raise TypeError("Cannot instantiate abstract Partial class.")
|
|
38
|
+
|
|
39
|
+
def __init_subclass__(
|
|
40
|
+
cls,
|
|
41
|
+
*args: object,
|
|
42
|
+
**kwargs: object,
|
|
43
|
+
) -> NoReturn:
|
|
44
|
+
"""Cannot subclass.
|
|
45
|
+
|
|
46
|
+
Raises:
|
|
47
|
+
TypeError: Subclassing not allowed.
|
|
48
|
+
"""
|
|
49
|
+
raise TypeError(f"Cannot subclass {cls.__module__}.Partial")
|
|
50
|
+
|
|
51
|
+
def __class_getitem__(
|
|
52
|
+
cls,
|
|
53
|
+
wrapped_class: type[FormattableT],
|
|
54
|
+
) -> type[FormattableT]:
|
|
55
|
+
"""Convert model to a partial model with all fields being optionals."""
|
|
56
|
+
# TODO: Implement proper partial model generation
|
|
57
|
+
# For now, return the original class to avoid import errors
|
|
58
|
+
return wrapped_class
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""Type for the formatting module."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Generic, Literal, Protocol, runtime_checkable
|
|
5
|
+
from typing_extensions import TypeVar
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
|
|
9
|
+
# TODO: Support primitive types (e.g. `format=list[Book]`)
|
|
10
|
+
FormattableT = TypeVar("FormattableT", bound=BaseModel | None, default=None)
|
|
11
|
+
"""Type variable for structured response format types.
|
|
12
|
+
|
|
13
|
+
This TypeVar represents the type of structured output format that LLM responses
|
|
14
|
+
can be parsed into, or None if no format is specified.
|
|
15
|
+
If format is specified, it must extend Pydantic BaseModel.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
FormattingMode = Literal[
|
|
20
|
+
"strict",
|
|
21
|
+
"json",
|
|
22
|
+
"tool",
|
|
23
|
+
]
|
|
24
|
+
"""Available modes for response format generation.
|
|
25
|
+
|
|
26
|
+
- "strict": Use strict mode for structured outputs, asking the LLM to strictly adhere
|
|
27
|
+
to a given JSON schema. Not all providers or models support it, and may not be
|
|
28
|
+
compatible with tool calling. When making a call using this mode, an
|
|
29
|
+
`llm.FormattingModeNotSupportedError` error may be raised (if "strict" mode is wholly
|
|
30
|
+
unsupported), or an `llm.FeatureNotSupportedError` may be raised (if trying to use
|
|
31
|
+
strict along with tools and that is unsupported).
|
|
32
|
+
|
|
33
|
+
- "json": Use JSON mode for structured outputs. In contrast to strict mode, we ask the
|
|
34
|
+
LLM to output JSON as text, though without guarantees that the model will output
|
|
35
|
+
the expected format schema. If the provider has explicit JSON mode, it will be used;
|
|
36
|
+
otherwise, Mirascope will modify the system prompt to request JSON output. May
|
|
37
|
+
raise an `llm.FeatureNotSupportedError` if tools are present and the
|
|
38
|
+
model does not support tool calling when using JSON mode.
|
|
39
|
+
|
|
40
|
+
- "tool": Use forced tool calling to structure outputs. Mirascope will construct an
|
|
41
|
+
ad-hoc tool with the required json schema as tool args. When the LLM chooses that
|
|
42
|
+
tool, it will automatically be converted from a `ToolCall` into regular response
|
|
43
|
+
content (abstracting over the tool call). If other tools are present, they will
|
|
44
|
+
be handled as regular tool calls.
|
|
45
|
+
|
|
46
|
+
Note: When `llm.format` is not used, the provider will automatically choose a mode at call time.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass(kw_only=True)
|
|
51
|
+
class Format(Generic[FormattableT]):
|
|
52
|
+
"""Class representing a structured output format for LLM responses.
|
|
53
|
+
|
|
54
|
+
A `Format` contains metadata needed to describe a structured output type
|
|
55
|
+
to the LLM, including the expected schema. This class is not instantiated directly,
|
|
56
|
+
but is created by calling `llm.format`, or is automatically generated by LLM
|
|
57
|
+
providers when a `Formattable` is passed to a call method.
|
|
58
|
+
|
|
59
|
+
Example:
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from mirascope import llm
|
|
63
|
+
|
|
64
|
+
class Book:
|
|
65
|
+
title: str
|
|
66
|
+
author: str
|
|
67
|
+
|
|
68
|
+
print(llm.format(Book, mode="tool"))
|
|
69
|
+
```
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
name: str
|
|
73
|
+
"""The name of the response format."""
|
|
74
|
+
|
|
75
|
+
description: str | None
|
|
76
|
+
"""A description of the response format, if available."""
|
|
77
|
+
|
|
78
|
+
schema: dict[str, object]
|
|
79
|
+
"""JSON schema representation of the structured output format."""
|
|
80
|
+
|
|
81
|
+
mode: FormattingMode
|
|
82
|
+
"""The decorator-provided mode of the response format.
|
|
83
|
+
|
|
84
|
+
Determines how the LLM call may be modified in order to extract the expected format.
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
formatting_instructions: str | None
|
|
88
|
+
"""The formatting instructions that will be added to the LLM system prompt.
|
|
89
|
+
|
|
90
|
+
If the format type has a `formatting_instructions` class method, the output of that
|
|
91
|
+
call will be used for instructions. Otherwise, instructions may be auto-generated
|
|
92
|
+
based on the formatting mode.
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
formattable: type[FormattableT]
|
|
96
|
+
"""The `Formattable` type that this `Format` describes.
|
|
97
|
+
|
|
98
|
+
While the `FormattbleT` typevar allows for `None`, a `Format` will never be
|
|
99
|
+
constructed when the `FormattableT` is `None`, so you may treat this as
|
|
100
|
+
a `RequiredFormattableT` in practice.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@runtime_checkable
|
|
105
|
+
class HasFormattingInstructions(Protocol):
|
|
106
|
+
"""Protocol for classes that have been decorated with `@format()`."""
|
|
107
|
+
|
|
108
|
+
@classmethod
|
|
109
|
+
def formatting_instructions(cls) -> str | None: ...
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import contextlib
|
|
2
|
+
from collections.abc import AsyncIterator, Callable
|
|
3
|
+
from datetime import timedelta
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
from mcp import ClientSession
|
|
7
|
+
from mcp.client.session import ListRootsFnT, SamplingFnT
|
|
8
|
+
from mcp.client.sse import sse_client as mcp_sse_client
|
|
9
|
+
from mcp.client.stdio import StdioServerParameters
|
|
10
|
+
from mcp.client.streamable_http import (
|
|
11
|
+
streamablehttp_client as mcp_streamablehttp_client,
|
|
12
|
+
)
|
|
13
|
+
from mcp.shared._httpx_utils import McpHttpClientFactory
|
|
14
|
+
|
|
15
|
+
from ..tools import AsyncTool
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class MCPClient:
|
|
19
|
+
"""Mirascope wrapper around a MCP ClientSession.
|
|
20
|
+
|
|
21
|
+
It provides a way to get MCP results that are pre-converted into Mirascope-friendly
|
|
22
|
+
types.
|
|
23
|
+
|
|
24
|
+
The underlying MCP ClientSession may be accessed by .session if needed.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, session: ClientSession) -> None:
|
|
28
|
+
self._session = session
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def session(self) -> ClientSession:
|
|
32
|
+
"""Access the underlying MCP ClientSession if needed."""
|
|
33
|
+
return self._session
|
|
34
|
+
|
|
35
|
+
async def list_tools(self) -> list[AsyncTool]:
|
|
36
|
+
"""List all tools available on the MCP server.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
A list of dynamically created `llm.Tool`s.
|
|
40
|
+
"""
|
|
41
|
+
raise NotImplementedError()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@contextlib.asynccontextmanager
|
|
45
|
+
async def streamablehttp_client(
|
|
46
|
+
url: str,
|
|
47
|
+
headers: dict[str, str] | None = None,
|
|
48
|
+
timeout: float | timedelta | None = None,
|
|
49
|
+
sse_read_timeout: float | timedelta | None = None,
|
|
50
|
+
terminate_on_close: bool = True,
|
|
51
|
+
httpx_client_factory: McpHttpClientFactory | None = None,
|
|
52
|
+
auth: httpx.Auth | None = None,
|
|
53
|
+
) -> AsyncIterator[MCPClient]:
|
|
54
|
+
"""Create a Mirascope MCPClient using StreamableHTTP."""
|
|
55
|
+
kwargs = {}
|
|
56
|
+
if headers is not None:
|
|
57
|
+
kwargs["headers"] = headers
|
|
58
|
+
if timeout is not None:
|
|
59
|
+
kwargs["timeout"] = timeout
|
|
60
|
+
if sse_read_timeout is not None:
|
|
61
|
+
kwargs["sse_read_timeout"] = sse_read_timeout
|
|
62
|
+
if httpx_client_factory is not None:
|
|
63
|
+
kwargs["httpx_client_factory"] = httpx_client_factory
|
|
64
|
+
if auth is not None:
|
|
65
|
+
kwargs["auth"] = auth
|
|
66
|
+
|
|
67
|
+
async with (
|
|
68
|
+
mcp_streamablehttp_client(
|
|
69
|
+
url,
|
|
70
|
+
terminate_on_close=terminate_on_close,
|
|
71
|
+
**kwargs,
|
|
72
|
+
) as (read, write, get_session_id),
|
|
73
|
+
ClientSession(
|
|
74
|
+
read,
|
|
75
|
+
write,
|
|
76
|
+
) as session,
|
|
77
|
+
):
|
|
78
|
+
await session.initialize()
|
|
79
|
+
yield MCPClient(session)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@contextlib.asynccontextmanager
|
|
83
|
+
async def stdio_client(
|
|
84
|
+
server_parameters: StdioServerParameters,
|
|
85
|
+
read_stream_exception_handler: Callable[[Exception], None] | None = None,
|
|
86
|
+
) -> AsyncIterator[MCPClient]:
|
|
87
|
+
"""Create a Mirascope MCPClient using stdio."""
|
|
88
|
+
|
|
89
|
+
async with (
|
|
90
|
+
ClientSession(None, None) as session, # pyright: ignore [reportArgumentType]
|
|
91
|
+
):
|
|
92
|
+
raise NotImplementedError()
|
|
93
|
+
await session.initialize()
|
|
94
|
+
yield MCPClient(session)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@contextlib.asynccontextmanager
|
|
98
|
+
async def sse_client(
|
|
99
|
+
url: str,
|
|
100
|
+
list_roots_callback: ListRootsFnT | None = None,
|
|
101
|
+
read_timeout_seconds: timedelta | None = None,
|
|
102
|
+
sampling_callback: SamplingFnT | None = None,
|
|
103
|
+
session: ClientSession | None = None,
|
|
104
|
+
) -> AsyncIterator[MCPClient]:
|
|
105
|
+
"""Create a Mirascope MCPClient using sse."""
|
|
106
|
+
|
|
107
|
+
async with (
|
|
108
|
+
mcp_sse_client(url) as (read, write),
|
|
109
|
+
ClientSession(
|
|
110
|
+
read,
|
|
111
|
+
write,
|
|
112
|
+
read_timeout_seconds=read_timeout_seconds,
|
|
113
|
+
sampling_callback=sampling_callback,
|
|
114
|
+
list_roots_callback=list_roots_callback,
|
|
115
|
+
) as session,
|
|
116
|
+
):
|
|
117
|
+
await session.initialize()
|
|
118
|
+
yield MCPClient(session)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""The messages module for LLM interactions.
|
|
2
|
+
|
|
3
|
+
This module defines the message types used in LLM interactions. Messages are represented
|
|
4
|
+
as a unified `Message` class with different roles (system, user, assistant) and flexible
|
|
5
|
+
content arrays that can include text, images, audio, documents, and tool interactions.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .message import (
|
|
9
|
+
AssistantContent,
|
|
10
|
+
AssistantMessage,
|
|
11
|
+
Message,
|
|
12
|
+
SystemContent,
|
|
13
|
+
SystemMessage,
|
|
14
|
+
UserContent,
|
|
15
|
+
UserMessage,
|
|
16
|
+
assistant,
|
|
17
|
+
system,
|
|
18
|
+
user,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"AssistantContent",
|
|
23
|
+
"AssistantMessage",
|
|
24
|
+
"Message",
|
|
25
|
+
"SystemContent",
|
|
26
|
+
"SystemMessage",
|
|
27
|
+
"UserContent",
|
|
28
|
+
"UserMessage",
|
|
29
|
+
"assistant",
|
|
30
|
+
"system",
|
|
31
|
+
"user",
|
|
32
|
+
]
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"""The `Message` class and its utility constructors."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from typing import TYPE_CHECKING, Literal, TypeAlias
|
|
8
|
+
|
|
9
|
+
from ..content import AssistantContentPart, Text, UserContentPart
|
|
10
|
+
from ..types import Jsonable
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from ..clients import ModelId, Provider
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(kw_only=True)
|
|
17
|
+
class SystemMessage:
|
|
18
|
+
"""A system message that sets context and instructions for the conversation."""
|
|
19
|
+
|
|
20
|
+
role: Literal["system"] = "system"
|
|
21
|
+
"""The role of this message. Always "system"."""
|
|
22
|
+
|
|
23
|
+
content: Text
|
|
24
|
+
"""The content of this `SystemMesssage`."""
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(kw_only=True)
|
|
28
|
+
class UserMessage:
|
|
29
|
+
"""A user message containing input from the user."""
|
|
30
|
+
|
|
31
|
+
role: Literal["user"] = "user"
|
|
32
|
+
"""The role of this message. Always "user"."""
|
|
33
|
+
|
|
34
|
+
content: Sequence[UserContentPart]
|
|
35
|
+
"""The content of the user message."""
|
|
36
|
+
|
|
37
|
+
name: str | None = None
|
|
38
|
+
"""A name identifying the creator of this message."""
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass(kw_only=True)
|
|
42
|
+
class AssistantMessage:
|
|
43
|
+
"""An assistant message containing the model's response."""
|
|
44
|
+
|
|
45
|
+
role: Literal["assistant"] = "assistant"
|
|
46
|
+
"""The role of this message. Always "assistant"."""
|
|
47
|
+
|
|
48
|
+
content: Sequence[AssistantContentPart]
|
|
49
|
+
"""The content of the assistant message."""
|
|
50
|
+
|
|
51
|
+
name: str | None = None
|
|
52
|
+
"""A name identifying the creator of this message."""
|
|
53
|
+
|
|
54
|
+
provider: Provider | None
|
|
55
|
+
"""The LLM provider that generated this assistant message, if available."""
|
|
56
|
+
|
|
57
|
+
model_id: ModelId | None
|
|
58
|
+
"""The model identifier of the LLM that generated this assistant message, if available."""
|
|
59
|
+
|
|
60
|
+
raw_message: Jsonable | None
|
|
61
|
+
"""The provider-specific raw representation of this assistant message, if available.
|
|
62
|
+
|
|
63
|
+
If raw_content is truthy, then it may be used for provider-specific behavior when
|
|
64
|
+
resuming an LLM interaction that included this assistant message. For example, we can
|
|
65
|
+
reuse the provider-specific raw encoding rather than re-encoding the message from it's
|
|
66
|
+
Mirascope content representation. This may also take advantage of server-side provider
|
|
67
|
+
context, e.g. identifiers of reasoning context tokens that the provider generated.
|
|
68
|
+
|
|
69
|
+
If present, the content should be encoded as JSON-serializable data, and in a format
|
|
70
|
+
that matches representation the provider expects representing the Mirascope data.
|
|
71
|
+
This may involve e.g. converting Pydantic `BaseModel`s into plain dicts via `model_dump`.
|
|
72
|
+
|
|
73
|
+
Raw content is not required, as the Mirascope content can also be used to generate
|
|
74
|
+
a valid input to the provider (potentially without taking advantage of provider-specific
|
|
75
|
+
reasoning caches, etc). In that case raw content should be left empty.
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
Message: TypeAlias = SystemMessage | UserMessage | AssistantMessage
|
|
80
|
+
"""A message in an LLM interaction.
|
|
81
|
+
|
|
82
|
+
Messages have a role (system, user, or assistant) and content that is a sequence
|
|
83
|
+
of content parts. The content can include text, images, audio, documents, and
|
|
84
|
+
tool interactions.
|
|
85
|
+
|
|
86
|
+
For most use cases, prefer the convenience functions `system()`, `user()`, and
|
|
87
|
+
`assistant()` instead of directly creating `Message` objects.
|
|
88
|
+
|
|
89
|
+
Example:
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from mirascope import llm
|
|
93
|
+
|
|
94
|
+
messages = [
|
|
95
|
+
llm.messages.system("You are a helpful assistant."),
|
|
96
|
+
llm.messages.user("Hello, how are you?"),
|
|
97
|
+
]
|
|
98
|
+
```
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
UserContent: TypeAlias = str | UserContentPart | Sequence[str | UserContentPart]
|
|
102
|
+
"""Type alias for content that can fit into a `UserMessage`."""
|
|
103
|
+
|
|
104
|
+
AssistantContent: TypeAlias = (
|
|
105
|
+
str | AssistantContentPart | Sequence[str | AssistantContentPart]
|
|
106
|
+
)
|
|
107
|
+
"""Type alias for content that can fit into an `AssistantMessage`."""
|
|
108
|
+
|
|
109
|
+
SystemContent: TypeAlias = str | Text
|
|
110
|
+
"""Type alias for content that can fit into a `SystemMessage`."""
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def system(content: SystemContent) -> SystemMessage:
|
|
114
|
+
"""Creates a system message.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
content: The content of the message, which must be a `str` or `Text` content.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
A `SystemMessage`.
|
|
121
|
+
"""
|
|
122
|
+
promoted_content = Text(text=content) if isinstance(content, str) else content
|
|
123
|
+
return SystemMessage(content=promoted_content)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def user(
|
|
127
|
+
content: UserContent,
|
|
128
|
+
*,
|
|
129
|
+
name: str | None = None,
|
|
130
|
+
) -> UserMessage:
|
|
131
|
+
"""Creates a user message.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
content: The content of the message, which can be `str` or any `UserContent`,
|
|
135
|
+
or a sequence of such user content pieces.
|
|
136
|
+
name: Optional name to identify a specific user in multi-party conversations.
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
A `UserMessage`.
|
|
140
|
+
"""
|
|
141
|
+
if isinstance(content, str) or not isinstance(content, Sequence):
|
|
142
|
+
content = [content]
|
|
143
|
+
promoted_content = [
|
|
144
|
+
Text(text=part) if isinstance(part, str) else part for part in content
|
|
145
|
+
]
|
|
146
|
+
return UserMessage(content=promoted_content, name=name)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def assistant(
|
|
150
|
+
content: AssistantContent,
|
|
151
|
+
*,
|
|
152
|
+
provider: Provider | None,
|
|
153
|
+
model_id: ModelId | None,
|
|
154
|
+
raw_message: Jsonable | None = None,
|
|
155
|
+
name: str | None = None,
|
|
156
|
+
) -> AssistantMessage:
|
|
157
|
+
"""Creates an assistant message.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
content: The content of the message, which can be `str` or any `AssistantContent`,
|
|
161
|
+
or a sequence of assistant content pieces.
|
|
162
|
+
provider: Optional identifier of the provider that produced this message.
|
|
163
|
+
model_id: Optional id of the model that produced this message.
|
|
164
|
+
raw_message: Optional Jsonable object that contains the provider-specific
|
|
165
|
+
"raw" data representation of the content for this assistant message.
|
|
166
|
+
name: Optional name to identify a specific assistant in multi-party conversations.
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
An `AssistantMessage`.
|
|
170
|
+
"""
|
|
171
|
+
if isinstance(content, str) or not isinstance(content, Sequence):
|
|
172
|
+
content = [content]
|
|
173
|
+
promoted_content = [
|
|
174
|
+
Text(text=part) if isinstance(part, str) else part for part in content
|
|
175
|
+
]
|
|
176
|
+
return AssistantMessage(
|
|
177
|
+
content=promoted_content,
|
|
178
|
+
provider=provider,
|
|
179
|
+
model_id=model_id,
|
|
180
|
+
raw_message=raw_message,
|
|
181
|
+
name=name,
|
|
182
|
+
)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""The `llm.models` module for implementing the `Model` interface and utilities.
|
|
2
|
+
|
|
3
|
+
This module provides a unified interface for interacting with different LLM models
|
|
4
|
+
through the `Model` class. The `llm.model()` context manager allows you to override
|
|
5
|
+
the model at runtime, and `llm.use_model()` retrieves the model from context or
|
|
6
|
+
creates a default one.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .models import Model, get_model_from_context, model, use_model
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"Model",
|
|
13
|
+
"get_model_from_context",
|
|
14
|
+
"model",
|
|
15
|
+
"use_model",
|
|
16
|
+
]
|