Mirascope Tutorial: A Pythonic Toolkit for Building LLM Applications
Introduction
Mirascope is a Python library that provides a clean, Pythonic interface for interacting with Large Language Models (LLMs). Unlike heavyweight frameworks such as LangChain that introduce multiple layers of abstraction, Mirascope takes a minimalist approach by leveraging native Python features like decorators, type hints, and Pydantic models.
Mirascope's key strength lies in its ability to simplify prompt engineering, structured output extraction, and tool calling without sacrificing flexibility. The library supports multiple LLM providers including OpenAI, Anthropic, Google Gemini, Mistral, Groq, and Cohere through a single consistent API.
In this tutorial, we'll learn how to use Mirascope from installation, basic prompt engineering, structured output, tool calling, to advanced techniques like chaining, streaming, and response model validation.
Why Mirascope?
Before diving into implementation, here's why Mirascope is worth considering:
Installation
Basic Installation
Mirascope can be installed using pip with your desired provider:
# Install core mirascope
pip install mirascope
Install with specific providers
pip install "mirascope[openai]"
pip install "mirascope[anthropic]"
pip install "mirascope[gemini]"
pip install "mirascope[groq]"
Install with all providers
pip install "mirascope[all]"
Setting Up Environment Variables
Configure API keys for your chosen provider:
# OpenAI
export OPENAIAPIKEY="sk-your-openai-key"
Anthropic
export ANTHROPICAPIKEY="sk-ant-your-anthropic-key"
Google Gemini
export GOOGLEAPIKEY="your-google-key"
Groq
export GROQAPIKEY="your-groq-key"
Or use a .env file with python-dotenv:
pip install python-dotenv
from dotenv import loaddotenv
load
dotenv()
Verify Installation
import mirascope
print(f"Mirascope version: {mirascope.version}")
Basic Usage: Prompt Engineering
Creating Simple Prompts with Decorators
Mirascope uses the @prompttemplate decorator and call functions to generate LLM responses:
from mirascope.core import openai, prompttemplate
@openai.call("gpt-4o-mini")
@prompttemplate("Explain {topic} in 3 paragraphs")
def explain(topic: str): ...
response = explain("machine learning")
print(response.content)
The code above is remarkably concise. The @openai.call decorator specifies the provider and model, while @prompttemplate defines the prompt template. The topic parameter is automatically injected into the template.
Multi-Provider Support
One of Mirascope's key advantages is the ease of switching between providers:
from mirascope.core import openai, anthropic, gemini, prompttemplate
@openai.call("gpt-4o-mini")
@prompt
template("What is {concept}?")
def askopenai(concept: str): ...
@anthropic.call("claude-sonnet-4-20250514")
@prompttemplate("What is {concept}?")
def askanthropic(concept: str): ...
@gemini.call("gemini-1.5-flash")
@prompttemplate("What is {concept}?")
def askgemini(concept: str): ...
All functions share the same interface
for askfn in [askopenai, askanthropic, askgemini]:
response = askfn("neural network")
print(f"[{askfn.name}]: {response.content[:100]}...")
System Prompts and Messages
For more complex scenarios, you can use messages directly:
from mirascope.core import openai, Messages
@openai.call("gpt-4o-mini")
def translate(text: str, targetlang: str) -> Messages.Type: