Seamlessly integrate LLMs as Python functions
Project description
magentic
Installation
pip install magentic
or using poetry
poetry add magentic
Configure your OpenAI API key by setting the OPENAI_API_KEY
environment variable or using openai.api_key = "sk-..."
. See the OpenAI Python library documentation for more information.
Usage
The @prompt
decorator allows you to define a template for a Large Language Model (LLM) prompt as a Python function.
from magentic import prompt
@prompt("What is a good name for a company that makes {product}?")
def get_company_name(product: str) -> str:
... # No code required!
get_company_name(product="colorful socks")
# 'Colorful Threads'
The @prompt
decorator will respect the return type annotation of the decorated function. This can be any type supported by pydantic including a pydantic
model.
from magentic import prompt
from pydantic import BaseModel
class Superhero(BaseModel):
name: str
age: int
power: str
enemies: list[str]
@prompt("Create a Superhero named {name}.")
def create_superhero(name: str) -> Superhero:
...
create_superhero("Garden Man")
# Superhero(name='Garden Man', age=30, power='Control over plants', enemies=['Pollution Man', 'Concrete Woman'])
An LLM can also decide to call functions. In this case the @prompt
-decorated function returns a FunctionCall
object which can be called to execute the function using the arguments provided by the LLM.
from typing import Literal
from magentic import prompt, FunctionCall
def activate_oven(temperature: int, mode: Literal["broil", "bake", "roast"]) -> str:
"""Turn the oven on with the provided settings."""
return f"Preheating to {temperature} F with mode {mode}"
@prompt(
template="Prepare the oven so I can make {food}",
functions=[activate_oven],
)
def configure_oven(food: str) -> FunctionCall[str]:
...
output = configure_oven("cookies!")
# FunctionCall(<function activate_oven at 0x1105a6200>, temperature=350, mode='bake')
output()
# 'Preheating to 350 F with mode bake'
Sometimes the LLM requires making one or more function calls to generate a final answer. The @prompt_chain
decorator will resolve FunctionCall
objects automatically and pass the output back to the LLM to continue until the final answer is reached.
In the following example the LLM first calls the get_current_weather
function, then uses the result to formulate its final answer.
from magentic import prompt_chain
def get_current_weather(location, unit="fahrenheit"):
"""Get the current weather in a given location"""
# Pretend to query an API
return {
"location": location,
"temperature": "72",
"unit": unit,
"forecast": ["sunny", "windy"],
}
@prompt_chain(
template="What's the weather like in {city}?",
functions=[get_current_weather],
)
def describe_weather(city: str) -> str:
...
describe_weather("Boston")
# 'The current weather in Boston is 72°F and it is sunny and windy.'
LLM-powered functions created using @prompt
and @prompt_chain
can be supplied as functions
to other @prompt
/@prompt_chain
decorators, just like regular python functions. This enables increasingly complex LLM-powered functionality, while allowing individual components to be tested and improved in isolation.
Additional Features
- The docstring of the decorated function will be used as the prompt template if the
template
argument is not provided to@prompt
/@prompt_chain
. - The
Annotated
type annotation can be used to provide descriptions and other metadata for function parameters. See the pydantic documentation on usingField
to describe function arguments. - The
@prompt
and@prompt_chain
decorators also accept amodel
argument. You can pass an instance ofOpenaiChatModel
(frommagentic.chat_model.openai_chat_model
) to use GPT4 or configure a different temperature.
Type Checking
Many type checkers will raise warnings or errors for functions with the prompt
decorator due to the function having no body or return value. There are several ways to deal with these.
- Disable the check globally for the type checker. For example in mypy by disabling error code
empty-body
.# pyproject.toml [tool.mypy] disable_error_code = ["empty-body"]
- Make the function body
...
(this does not satisfy mypy) orraise
.@prompt() def random_color() -> str: """Choose a color""" ...
- Use comment
# type: ignore[empty-body]
on each function.@prompt() def random_color() -> str: # type: ignore[empty-body] """Choose a color"""
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.