Skip to content

mirascope api

mirascope package.

BaseCallParams

Bases: BaseModel, Generic[BaseToolT]

The parameters with which to make a call.

Source code in mirascope/base/types.py
class BaseCallParams(BaseModel, Generic[BaseToolT]):
    """The parameters with which to make a call."""

    model: str
    tools: Optional[list[Union[Callable, Type[BaseToolT]]]] = None

    model_config = ConfigDict(extra="allow", arbitrary_types_allowed=True)

    def kwargs(
        self,
        tool_type: Optional[Type[BaseToolT]] = None,
        exclude: Optional[set[str]] = None,
    ) -> dict[str, Any]:
        """Returns all parameters for the call as a keyword arguments dictionary."""
        extra_exclude = {"tools"}
        exclude = extra_exclude if exclude is None else exclude.union(extra_exclude)
        kwargs = {
            key: value
            for key, value in self.model_dump(exclude=exclude).items()
            if value is not None
        }
        if not self.tools or tool_type is None:
            return kwargs
        kwargs["tools"] = [
            tool if isclass(tool) else convert_function_to_tool(tool, tool_type)
            for tool in self.tools
        ]
        return kwargs

kwargs(tool_type=None, exclude=None)

Returns all parameters for the call as a keyword arguments dictionary.

Source code in mirascope/base/types.py
def kwargs(
    self,
    tool_type: Optional[Type[BaseToolT]] = None,
    exclude: Optional[set[str]] = None,
) -> dict[str, Any]:
    """Returns all parameters for the call as a keyword arguments dictionary."""
    extra_exclude = {"tools"}
    exclude = extra_exclude if exclude is None else exclude.union(extra_exclude)
    kwargs = {
        key: value
        for key, value in self.model_dump(exclude=exclude).items()
        if value is not None
    }
    if not self.tools or tool_type is None:
        return kwargs
    kwargs["tools"] = [
        tool if isclass(tool) else convert_function_to_tool(tool, tool_type)
        for tool in self.tools
    ]
    return kwargs

BasePrompt

Bases: BaseModel

The base class for working with prompts.

This class is implemented as the base for all prompting needs across various model providers.

Example:

from mirascope import BasePrompt


class BookRecommendationPrompt(BasePrompt):
    """A prompt for recommending a book."""

    prompt_template = """
    SYSTEM: You are the world's greatest librarian.
    USER: Please recommend a {genre} book.
    """

    genre: str


prompt = BookRecommendationPrompt(genre="fantasy")
print(prompt.messages())
#> [{"role": "user", "content": "Please recommend a fantasy book."}]

print(prompt)
#> Please recommend a fantasy book.
Source code in mirascope/base/prompts.py
class BasePrompt(BaseModel):
    '''The base class for working with prompts.

    This class is implemented as the base for all prompting needs across various model
    providers.

    Example:

    ```python
    from mirascope import BasePrompt


    class BookRecommendationPrompt(BasePrompt):
        """A prompt for recommending a book."""

        prompt_template = """
        SYSTEM: You are the world's greatest librarian.
        USER: Please recommend a {genre} book.
        """

        genre: str


    prompt = BookRecommendationPrompt(genre="fantasy")
    print(prompt.messages())
    #> [{"role": "user", "content": "Please recommend a fantasy book."}]

    print(prompt)
    #> Please recommend a fantasy book.
    ```
    '''

    tags: ClassVar[list[str]] = []
    prompt_template: ClassVar[str] = ""

    def __str__(self) -> str:
        """Returns the formatted template."""
        return self._format_template(self.prompt_template)

    def messages(self) -> Union[list[Message], Any]:
        """Returns the template as a formatted list of messages."""
        message_type_by_role = {
            MessageRole.SYSTEM: SystemMessage,
            MessageRole.USER: UserMessage,
            MessageRole.ASSISTANT: AssistantMessage,
            MessageRole.MODEL: ModelMessage,
            MessageRole.TOOL: ToolMessage,
        }
        return [
            message_type_by_role[MessageRole(message["role"])](**message)
            for message in self._parse_messages(list(message_type_by_role.keys()))
        ]

    def dump(
        self,
    ) -> dict[str, Any]:
        """Dumps the contents of the prompt into a dictionary."""
        return {
            "tags": self.tags,
            "template": dedent(self.prompt_template).strip("\n"),
            "inputs": self.model_dump(),
        }

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

    def _format_template(self, template: str):
        """Formats the given `template` with attributes matching template variables."""
        dedented_template = dedent(template).strip()
        template_vars = [
            var
            for _, var, _, _ in Formatter().parse(dedented_template)
            if var is not None
        ]

        values = {}
        for var in template_vars:
            attr = getattr(self, var)
            if attr and isinstance(attr, list):
                if isinstance(attr[0], list):
                    values[var] = "\n\n".join(
                        ["\n".join([str(subitem) for subitem in item]) for item in attr]
                    )
                else:
                    values[var] = "\n".join([str(item) for item in attr])
            else:
                values[var] = str(attr)

        return dedented_template.format(**values)

    def _parse_messages(self, roles: list[str]) -> list[Message]:
        """Returns messages parsed from the `template` ClassVar.

        Raises:
            ValueError: if the template contains an unknown role.
        """
        messages = []
        re_roles = "|".join([role.upper() for role in roles] + ["MESSAGES"])
        for match in re.finditer(
            rf"({re_roles}):((.|\n)+?)(?=({re_roles}):|\Z)",
            self.prompt_template,
        ):
            role = match.group(1).lower()
            if role == "messages":
                template_var = [
                    var
                    for _, var, _, _ in Formatter().parse(match.group(2))
                    if var is not None
                ][0]
                attribute = getattr(self, template_var)
                if attribute is None or not isinstance(attribute, list):
                    raise ValueError(
                        f"MESSAGES keyword used with attribute `{template_var}`, which "
                        "is not a `list` of messages."
                    )
                messages += attribute
            else:
                content = self._format_template(match.group(2))
                if content:
                    messages.append({"role": role, "content": content})
        if len(messages) == 0:
            messages.append(
                {
                    "role": "user",
                    "content": self._format_template(self.prompt_template),
                }
            )
        return messages

dump()

Dumps the contents of the prompt into a dictionary.

Source code in mirascope/base/prompts.py
def dump(
    self,
) -> dict[str, Any]:
    """Dumps the contents of the prompt into a dictionary."""
    return {
        "tags": self.tags,
        "template": dedent(self.prompt_template).strip("\n"),
        "inputs": self.model_dump(),
    }

messages()

Returns the template as a formatted list of messages.

Source code in mirascope/base/prompts.py
def messages(self) -> Union[list[Message], Any]:
    """Returns the template as a formatted list of messages."""
    message_type_by_role = {
        MessageRole.SYSTEM: SystemMessage,
        MessageRole.USER: UserMessage,
        MessageRole.ASSISTANT: AssistantMessage,
        MessageRole.MODEL: ModelMessage,
        MessageRole.TOOL: ToolMessage,
    }
    return [
        message_type_by_role[MessageRole(message["role"])](**message)
        for message in self._parse_messages(list(message_type_by_role.keys()))
    ]

tags(args)

A decorator for adding tags to a BasePrompt.

Adding this decorator to a BasePrompt updates the _tags class attribute to the given value. This is useful for adding metadata to a BasePrompt that can be used for logging or filtering.

Example:

from mirascope import BasePrompt, tags


@tags(["book_recommendation", "entertainment"])
class BookRecommendationPrompt(BasePrompt):
    prompt_template = """
    SYSTEM:
    You are the world's greatest librarian.

    USER:
    I've recently read this book: {book_title}.
    What should I read next?
    """

    book_title: [str]

print(BookRecommendationPrompt.dump()["tags"])
#> ['book_recommendation', 'entertainment']

Returns:

Type Description
Callable[[Type[BasePromptT]], Type[BasePromptT]]

The decorated class with tags class attribute set.

Source code in mirascope/base/prompts.py
def tags(args: list[str]) -> Callable[[Type[BasePromptT]], Type[BasePromptT]]:
    '''A decorator for adding tags to a `BasePrompt`.

    Adding this decorator to a `BasePrompt` updates the `_tags` class attribute to the
    given value. This is useful for adding metadata to a `BasePrompt` that can be used
    for logging or filtering.

    Example:

    ```python
    from mirascope import BasePrompt, tags


    @tags(["book_recommendation", "entertainment"])
    class BookRecommendationPrompt(BasePrompt):
        prompt_template = """
        SYSTEM:
        You are the world's greatest librarian.

        USER:
        I've recently read this book: {book_title}.
        What should I read next?
        """

        book_title: [str]

    print(BookRecommendationPrompt.dump()["tags"])
    #> ['book_recommendation', 'entertainment']
    ```

    Returns:
        The decorated class with `tags` class attribute set.
    '''

    def tags_fn(model_class: Type[BasePromptT]) -> Type[BasePromptT]:
        """Updates the `tags` class attribute to the given value."""
        setattr(model_class, "tags", args)
        return model_class

    return tags_fn