Manifest ✨
Call an LLM by calling a function.
- Define a function name, arguments, return value, and docstring.
- Call your function as normal, passing in your values.
- For those values, an LLM will return a response that conforms to your return type.
Installation
pip install manifest
Now make sure your OpenAI key is set:
export OPENAI_API_KEY="your_api_key_here"
Examples
Sentiment analysis
from manifest import ai
@ai
def is_optimistic(text: str) -> bool:
"""Determines if the text is optimistic"""
print(is_optimistic("This is amazing!")) # Prints True
Translation
from manifest import ai
@ai
def translate(english_text: str, target_lang: str) -> str:
"""Translates text from english into a target language"""
print(translate("Hello", "fr")) # Prints "Bonjour"
Image analysis
from pathlib import Path
from manifest import ai
@ai
def breed_of_dog(image: Path) -> str:
"""Determines the breed of dog from a photo"""
image = Path("path/to/dog.jpg")
print(breed_of_dog(image)) # Prints "German Shepherd" (or whatever)
Complex objects
from dataclasses import dataclass
from manifest import ai
@dataclass
class Actor:
name: str
character: str
@dataclass
class Movie:
title: str
director: str
year: int
top_cast: list[Actor]
@ai
def similar_movie(movie: str, before_year: int | None=None) -> Movie:
"""Discovers a similar movie, before a certain year, if the year is
provided."""
like_inception = similar_movie("Inception")
print(like_inception) # Prints a movie similar to inception
Recursive types
It can handle self-referential types. For example, each Character has a social_graph, and each SocialGraph is composed of Characters.
from dataclasses import dataclass
from pprint import pprint
from manifest import ai
@dataclass
class Character:
name: str
occupation: str
social_graph: "SocialGraph"
@dataclass
class SocialGraph:
friends: list[Character]
enemies: list[Character]
@ai
def get_character_social_graph(character_name: str) -> SocialGraph:
"""For a given fictional character, return their social graph, resolving
each friend and enemy's social graph recursively."""
graph = get_character_social_graph("Walter White")
pprint(graph)
SocialGraph(
friends=[
Character(
name='Jesse Pinkman',
occupation='Meth Manufacturer',
social_graph=SocialGraph(
friends=[Character(name='Walter White', occupation='Chemistry Teacher', social_graph=SocialGraph(friends=[], enemies=[]))],
enemies=[Character(name='Hank Schrader', occupation='DEA Agent', social_graph=SocialGraph(friends=[], enemies=[]))]
)
),
Character(
name='Saul Goodman',
occupation='Lawyer',
social_graph=SocialGraph(friends=[Character(name='Walter White', occupation='Chemistry Teacher', social_graph=SocialGraph(friends=[], enemies=[]))], enemies=[])
)
],
enemies=[
Character(
name='Hank Schrader',
occupation='DEA Agent',
social_graph=SocialGraph(
friends=[Character(name='Marie Schrader', occupation='Radiologic Technologist', social_graph=SocialGraph(friends=[], enemies=[]))],
enemies=[Character(name='Walter White', occupation='Meth Manufacturer', social_graph=SocialGraph(friends=[], enemies=[]))]
)
),
Character(
name='Gus Fring',
occupation='Businessman',
social_graph=SocialGraph(
friends=[Character(name='Mike Ehrmantraut', occupation='Fixer', social_graph=SocialGraph(friends=[], enemies=[]))],
enemies=[Character(name='Walter White', occupation='Meth Manufacturer', social_graph=SocialGraph(friends=[], enemies=[]))]
)
)
]
)
How does it work?
Manifest relies heavily on runtime metadata, such as a function's name, docstring, arguments, and type hints. It uses all of these to compose a prompt behind the scenes, then sends the prompt to an LLM. The LLM "executes" the prompt, and returns a json-based format that we can safely parse back into the appropriate object.
To get the most out the @ai decorator:
- Name your function well.
- Add type hints to your function.
- Add a high-value docstring to your function.
Limitations
REPL
Manifest doesn't work from the REPL, due to it needing access to the source code of the functions it decorates.
Types
You can only pass in and return the following types:
- Dataclasses
Enumsubclasses- primitives (str, int, bool, None, etc)
- basic container types (list, dict, tuple)
- unions
- Any combination of the above
Prompts
The prompt templates are also a little fiddly sometimes. They can be improved.
Initialization
To make things super simple, manifest uses ambient LLM credentials, currently
just OPENAI_API_KEY. If environment credentials are not found, you will be
instructed to initialize the library yourself.
Release files for manifest 0.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| manifest-0.6.0.tar.gz | 15.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| manifest-0.6.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 37.3 kB
Release files / manifest-0.6.0.tar.gz
| Download URL | manifest-0.6.0.tar.gz |
|---|---|
| Size | 15.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7dab5403869149c4cfd6c5b66be1e9a3034e4e39720107b387c8c456752cdb02
|
|
BLAKE2b-256 checksum How to use checksums |
a70d95147e6c3b47d7380130a3800aae3193d392cb274fc8b74c81468ed6fd5a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.8.3 CPython/3.12.3 Linux/6.8.0-41-generic
|
Release files / manifest-0.6.0-py3-none-any.whl
| Download URL | manifest-0.6.0-py3-none-any.whl |
|---|---|
| Size | 21.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
94b0929df89d13f9a908f7207f79796cb3cfd8695f27dae5bdd88b7583333fa9
|
|
BLAKE2b-256 checksum How to use checksums |
5eb3125e8b78ce6871fbbe8691876896b4fea8d8d90c6dc265dd20386e0eb1cb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.8.3 CPython/3.12.3 Linux/6.8.0-41-generic
|