Skip to content

anthropic.calls

A module for calling Anthropic's Claude API.

AnthropicCall

Bases: BaseCall[AnthropicCallResponse, AnthropicCallResponseChunk, AnthropicTool]

A base class for calling Anthropic's Claude models.

Example:

from mirascope.anthropic import AnthropicCall


class BookRecommender(AnthropicCall):
    prompt_template = "Please recommend a {genre} book."

    genre: str


response = BookRecommender(genre="fantasy").call()
print(response.content)
#> There are many great books to read, it ultimately depends...
Source code in mirascope/anthropic/calls.py
class AnthropicCall(
    BaseCall[AnthropicCallResponse, AnthropicCallResponseChunk, AnthropicTool]
):
    """A base class for calling Anthropic's Claude models.

    Example:

    ```python
    from mirascope.anthropic import AnthropicCall


    class BookRecommender(AnthropicCall):
        prompt_template = "Please recommend a {genre} book."

        genre: str


    response = BookRecommender(genre="fantasy").call()
    print(response.content)
    #> There are many great books to read, it ultimately depends...
    ```
    """

    call_params: ClassVar[AnthropicCallParams] = AnthropicCallParams()
    _provider: ClassVar[str] = "anthropic"

    def messages(self) -> list[MessageParam]:
        """Returns the template as a formatted list of messages."""
        return self._parse_messages(
            [MessageRole.SYSTEM, MessageRole.USER, MessageRole.ASSISTANT]
        )  # type: ignore

    @retry
    def call(
        self, retries: Union[int, Retrying] = 0, **kwargs: Any
    ) -> AnthropicCallResponse:
        """Makes a call to the model using this `AnthropicCall` instance.

        Args:
            **kwargs: Additional keyword arguments parameters to pass to the call. These
                will override any existing arguments in `call_params`.

        Returns:
            A `AnthropicCallResponse` instance.
        """
        messages, kwargs, tool_types = self._setup_anthropic_kwargs(kwargs)
        client = get_wrapped_client(
            Anthropic(api_key=self.api_key, base_url=self.base_url), self
        )
        create = client.messages.create
        if tool_types:
            create = client.beta.tools.messages.create  # type: ignore
        create = get_wrapped_call(
            create,
            self,
            response_type=AnthropicCallResponse,
            tool_types=tool_types,
        )
        start_time = datetime.datetime.now().timestamp() * 1000
        message = create(
            messages=messages,
            stream=False,
            **kwargs,
        )
        return AnthropicCallResponse(
            response=message,
            tool_types=tool_types,
            start_time=start_time,
            end_time=datetime.datetime.now().timestamp() * 1000,
            cost=anthropic_api_calculate_cost(message.usage, message.model),
            response_format=self.call_params.response_format,
        )

    @retry
    async def call_async(
        self, retries: Union[int, AsyncRetrying] = 0, **kwargs: Any
    ) -> AnthropicCallResponse:
        """Makes an asynchronous call to the model using this `AnthropicCall` instance.

        Args:
            **kwargs: Additional keyword arguments parameters to pass to the call. These
                will override any existing arguments in `call_params`.

        Returns:
            A `AnthropicCallResponse` instance.
        """
        messages, kwargs, tool_types = self._setup_anthropic_kwargs(kwargs)
        client = get_wrapped_async_client(
            AsyncAnthropic(api_key=self.api_key, base_url=self.base_url), self
        )
        create = client.messages.create
        if tool_types:
            create = client.beta.tools.messages.create  # type: ignore
        create = get_wrapped_call(
            create,
            self,
            is_async=True,
            response_type=AnthropicCallResponse,
            tool_types=tool_types,
        )
        start_time = datetime.datetime.now().timestamp() * 1000
        message = await create(
            messages=messages,
            stream=False,
            **kwargs,
        )
        return AnthropicCallResponse(
            response=message,
            tool_types=tool_types,
            start_time=start_time,
            end_time=datetime.datetime.now().timestamp() * 1000,
            cost=anthropic_api_calculate_cost(message.usage, message.model),
            response_format=self.call_params.response_format,
        )

    @retry
    def stream(
        self, retries: Union[int, Retrying] = 0, **kwargs: Any
    ) -> Generator[AnthropicCallResponseChunk, None, None]:
        """Streams the response for a call using this `AnthropicCall`.

        Args:
            **kwargs: Additional keyword arguments parameters to pass to the call. These
                will override any existing arguments in `call_params`.

        Yields:
            An `AnthropicCallResponseChunk` for each chunk of the response.
        """
        messages, kwargs, tool_types = self._setup_anthropic_kwargs(kwargs)
        client = get_wrapped_client(
            Anthropic(api_key=self.api_key, base_url=self.base_url), self
        )
        stream_fn = get_wrapped_call(
            client.messages.stream,
            self,
            response_chunk_type=AnthropicCallResponseChunk,
            tool_types=tool_types,
        )
        stream = stream_fn(messages=messages, **kwargs)
        if isinstance(stream, AbstractContextManager):
            with stream as message_stream:
                for chunk in message_stream:
                    yield AnthropicCallResponseChunk(
                        chunk=chunk,
                        tool_types=tool_types,
                        response_format=self.call_params.response_format,
                    )
        else:
            for chunk in stream:  # type: ignore
                yield AnthropicCallResponseChunk(
                    chunk=chunk,
                    tool_types=tool_types,
                    response_format=self.call_params.response_format,
                )

    @retry
    async def stream_async(
        self, retries: Union[int, AsyncRetrying] = 0, **kwargs: Any
    ) -> AsyncGenerator[AnthropicCallResponseChunk, None]:
        """Streams the response for an asynchronous call using this `AnthropicCall`.

        Args:
            **kwargs: Additional keyword arguments parameters to pass to the call. These
                will override any existing arguments in `call_params`.

        Yields:
            An `AnthropicCallResponseChunk` for each chunk of the response.
        """
        messages, kwargs, tool_types = self._setup_anthropic_kwargs(kwargs)
        client = get_wrapped_async_client(
            AsyncAnthropic(api_key=self.api_key, base_url=self.base_url), self
        )
        stream_fn = get_wrapped_call(
            client.messages.stream,
            self,
            is_async=True,
            response_chunk_type=AnthropicCallResponseChunk,
            tool_types=tool_types,
        )
        stream = stream_fn(messages=messages, **kwargs)
        if isinstance(stream, AbstractAsyncContextManager):
            async with stream as message_stream:
                async for chunk in message_stream:  # type: ignore
                    yield AnthropicCallResponseChunk(
                        chunk=chunk,
                        tool_types=tool_types,
                        response_format=self.call_params.response_format,
                    )
        else:
            async for chunk in stream:  # type: ignore
                yield AnthropicCallResponseChunk(
                    chunk=chunk,
                    tool_types=tool_types,
                    response_format=self.call_params.response_format,
                )

    ############################## PRIVATE METHODS ###################################

    def _setup_anthropic_kwargs(
        self,
        kwargs: dict[str, Any],
    ) -> tuple[
        list[MessageParam],
        dict[str, Any],
        Optional[list[Type[AnthropicTool]]],
    ]:
        """Overrides the `BaseCall._setup` for Anthropic specific setup."""
        kwargs, tool_types = self._setup(kwargs, AnthropicTool)
        messages = self.messages()
        system_message = ""
        if "system" in kwargs and kwargs["system"] is not None:
            system_message += f'{kwargs.pop("system")}'
        if messages[0]["role"] == "system":
            if system_message:
                system_message += "\n"
            system_message += messages.pop(0)["content"]
        if self.call_params.response_format == "json":
            if system_message:
                system_message += "\n\n"
            system_message += "Response format: JSON."
            messages.append(
                {
                    "role": "assistant",
                    "content": "Here is the JSON requested with only the fields "
                    "defined in the schema you provided:\n{",
                }
            )
            if "tools" in kwargs:
                tools = kwargs.pop("tools")
                messages[-1]["content"] = (
                    "For each JSON you output, output ONLY the fields defined by these "
                    "schemas. Include a `tool_name` field that EXACTLY MATCHES the "
                    "tool name found in the schema matching this tool:"
                    "\n{schemas}\n{json_msg}".format(
                        schemas="\n\n".join([str(tool) for tool in tools]),
                        json_msg=messages[-1]["content"],
                    )
                )
        if system_message:
            kwargs["system"] = system_message

        return messages, kwargs, tool_types

call(retries=0, **kwargs)

Makes a call to the model using this AnthropicCall instance.

Parameters:

Name Type Description Default
**kwargs Any

Additional keyword arguments parameters to pass to the call. These will override any existing arguments in call_params.

{}

Returns:

Type Description
AnthropicCallResponse

A AnthropicCallResponse instance.

Source code in mirascope/anthropic/calls.py
@retry
def call(
    self, retries: Union[int, Retrying] = 0, **kwargs: Any
) -> AnthropicCallResponse:
    """Makes a call to the model using this `AnthropicCall` instance.

    Args:
        **kwargs: Additional keyword arguments parameters to pass to the call. These
            will override any existing arguments in `call_params`.

    Returns:
        A `AnthropicCallResponse` instance.
    """
    messages, kwargs, tool_types = self._setup_anthropic_kwargs(kwargs)
    client = get_wrapped_client(
        Anthropic(api_key=self.api_key, base_url=self.base_url), self
    )
    create = client.messages.create
    if tool_types:
        create = client.beta.tools.messages.create  # type: ignore
    create = get_wrapped_call(
        create,
        self,
        response_type=AnthropicCallResponse,
        tool_types=tool_types,
    )
    start_time = datetime.datetime.now().timestamp() * 1000
    message = create(
        messages=messages,
        stream=False,
        **kwargs,
    )
    return AnthropicCallResponse(
        response=message,
        tool_types=tool_types,
        start_time=start_time,
        end_time=datetime.datetime.now().timestamp() * 1000,
        cost=anthropic_api_calculate_cost(message.usage, message.model),
        response_format=self.call_params.response_format,
    )

call_async(retries=0, **kwargs) async

Makes an asynchronous call to the model using this AnthropicCall instance.

Parameters:

Name Type Description Default
**kwargs Any

Additional keyword arguments parameters to pass to the call. These will override any existing arguments in call_params.

{}

Returns:

Type Description
AnthropicCallResponse

A AnthropicCallResponse instance.

Source code in mirascope/anthropic/calls.py
@retry
async def call_async(
    self, retries: Union[int, AsyncRetrying] = 0, **kwargs: Any
) -> AnthropicCallResponse:
    """Makes an asynchronous call to the model using this `AnthropicCall` instance.

    Args:
        **kwargs: Additional keyword arguments parameters to pass to the call. These
            will override any existing arguments in `call_params`.

    Returns:
        A `AnthropicCallResponse` instance.
    """
    messages, kwargs, tool_types = self._setup_anthropic_kwargs(kwargs)
    client = get_wrapped_async_client(
        AsyncAnthropic(api_key=self.api_key, base_url=self.base_url), self
    )
    create = client.messages.create
    if tool_types:
        create = client.beta.tools.messages.create  # type: ignore
    create = get_wrapped_call(
        create,
        self,
        is_async=True,
        response_type=AnthropicCallResponse,
        tool_types=tool_types,
    )
    start_time = datetime.datetime.now().timestamp() * 1000
    message = await create(
        messages=messages,
        stream=False,
        **kwargs,
    )
    return AnthropicCallResponse(
        response=message,
        tool_types=tool_types,
        start_time=start_time,
        end_time=datetime.datetime.now().timestamp() * 1000,
        cost=anthropic_api_calculate_cost(message.usage, message.model),
        response_format=self.call_params.response_format,
    )

messages()

Returns the template as a formatted list of messages.

Source code in mirascope/anthropic/calls.py
def messages(self) -> list[MessageParam]:
    """Returns the template as a formatted list of messages."""
    return self._parse_messages(
        [MessageRole.SYSTEM, MessageRole.USER, MessageRole.ASSISTANT]
    )  # type: ignore

stream(retries=0, **kwargs)

Streams the response for a call using this AnthropicCall.

Parameters:

Name Type Description Default
**kwargs Any

Additional keyword arguments parameters to pass to the call. These will override any existing arguments in call_params.

{}

Yields:

Type Description
AnthropicCallResponseChunk

An AnthropicCallResponseChunk for each chunk of the response.

Source code in mirascope/anthropic/calls.py
@retry
def stream(
    self, retries: Union[int, Retrying] = 0, **kwargs: Any
) -> Generator[AnthropicCallResponseChunk, None, None]:
    """Streams the response for a call using this `AnthropicCall`.

    Args:
        **kwargs: Additional keyword arguments parameters to pass to the call. These
            will override any existing arguments in `call_params`.

    Yields:
        An `AnthropicCallResponseChunk` for each chunk of the response.
    """
    messages, kwargs, tool_types = self._setup_anthropic_kwargs(kwargs)
    client = get_wrapped_client(
        Anthropic(api_key=self.api_key, base_url=self.base_url), self
    )
    stream_fn = get_wrapped_call(
        client.messages.stream,
        self,
        response_chunk_type=AnthropicCallResponseChunk,
        tool_types=tool_types,
    )
    stream = stream_fn(messages=messages, **kwargs)
    if isinstance(stream, AbstractContextManager):
        with stream as message_stream:
            for chunk in message_stream:
                yield AnthropicCallResponseChunk(
                    chunk=chunk,
                    tool_types=tool_types,
                    response_format=self.call_params.response_format,
                )
    else:
        for chunk in stream:  # type: ignore
            yield AnthropicCallResponseChunk(
                chunk=chunk,
                tool_types=tool_types,
                response_format=self.call_params.response_format,
            )

stream_async(retries=0, **kwargs) async

Streams the response for an asynchronous call using this AnthropicCall.

Parameters:

Name Type Description Default
**kwargs Any

Additional keyword arguments parameters to pass to the call. These will override any existing arguments in call_params.

{}

Yields:

Type Description
AsyncGenerator[AnthropicCallResponseChunk, None]

An AnthropicCallResponseChunk for each chunk of the response.

Source code in mirascope/anthropic/calls.py
@retry
async def stream_async(
    self, retries: Union[int, AsyncRetrying] = 0, **kwargs: Any
) -> AsyncGenerator[AnthropicCallResponseChunk, None]:
    """Streams the response for an asynchronous call using this `AnthropicCall`.

    Args:
        **kwargs: Additional keyword arguments parameters to pass to the call. These
            will override any existing arguments in `call_params`.

    Yields:
        An `AnthropicCallResponseChunk` for each chunk of the response.
    """
    messages, kwargs, tool_types = self._setup_anthropic_kwargs(kwargs)
    client = get_wrapped_async_client(
        AsyncAnthropic(api_key=self.api_key, base_url=self.base_url), self
    )
    stream_fn = get_wrapped_call(
        client.messages.stream,
        self,
        is_async=True,
        response_chunk_type=AnthropicCallResponseChunk,
        tool_types=tool_types,
    )
    stream = stream_fn(messages=messages, **kwargs)
    if isinstance(stream, AbstractAsyncContextManager):
        async with stream as message_stream:
            async for chunk in message_stream:  # type: ignore
                yield AnthropicCallResponseChunk(
                    chunk=chunk,
                    tool_types=tool_types,
                    response_format=self.call_params.response_format,
                )
    else:
        async for chunk in stream:  # type: ignore
            yield AnthropicCallResponseChunk(
                chunk=chunk,
                tool_types=tool_types,
                response_format=self.call_params.response_format,
            )