Skip to content

Commit

Permalink
Merge pull request #752 from PrefectHQ/docs-2
Browse files Browse the repository at this point in the history
Update docs
  • Loading branch information
jlowin authored Jan 16, 2024
2 parents 9e62f7b + eb2ff65 commit f483ab2
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 96 deletions.
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@
[![Twitter Follow](https://img.shields.io/twitter/follow/AskMarvinAI?style=social)](https://twitter.com/AskMarvinAI)

### The AI engineering toolkit
Marvin is a lightweight AI toolkit for building natural language interfaces that are reliable, scalable, and easy to trust. Marvin lets you use LLMs by writing code, not prompts. It's open source, free to use, rigorously type-hinted, and used by thousands of engineers.

Each of Marvin's tools is simple and self-documenting, using AI to solve common but complex challenges like entity extraction, generating example data, and classifying text. Each tool is independent and incrementally adoptable so you can use it alone or in combination with any other library. Marvin also has tools for multi-modal use cases like image generation, vision, and speech.
Marvin is a lightweight AI toolkit for building natural language interfaces that are reliable, scalable, and easy to trust.

Marvin is made with 💙 by the team at [Prefect](https://www.prefect.io/).
Each of Marvin's tools is simple and self-documenting, using AI to solve common but complex challenges like entity extraction, classification, and generating synthetic data. Each tool is independent and incrementally adoptable, so you can use them on their own or in combination with any other library. Marvin is also multi-modal, supporting both image and audio generation as well using images as inputs for extraction and classification.

Marvin is for developers who care more about *using* AI than *building* AI, and we are focused on creating an exceptional developer experience. Marvin users should feel empowered to bring tightly-scoped "AI magic" into any traditional software project with just a few extra lines of code.

Marvin aims to merge the best practices for building dependable, observable software with the best practices for building with generative AI into a single, easy-to-use library. It's a serious tool, but we hope you have fun with it.

Marvin is open-source, free to use, and made with 💙 by the team at [Prefect](https://www.prefect.io/).

## Installation

Expand Down
9 changes: 5 additions & 4 deletions docs/ai/text/extraction.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ Marvin's `extract` function is a robust tool for pulling lists of structured ent

features = marvin.extract(
"I love my new phone's camera, but the battery life could be improved.",
target=str,
instructions='list any product features',
instructions='get any product features that were mentioned',
)
```

Expand Down Expand Up @@ -67,9 +66,11 @@ Marvin's `extract` function is a robust tool for pulling lists of structured ent



## Supported types
## Supported targets

`extract` supports almost all builtin Python types, plus Pydantic models, Python's `Literal`, and `TypedDict`. Pydantic models are especially useful for extracting structured data, such as locations, dates, or more complex types. Builtin types are most useful in conjunction with instructions that provide more precise criteria for extraction.
`extract` supports almost all builtin Python types, plus Pydantic models, Python's `Literal`, and `TypedDict`. Pydantic models are especially useful for specifying specific features of the generated data, such as locations, dates, or more complex types. Builtin types are most useful in conjunction with instructions that provide more precise criteria for generation.

To specify the output type, pass it as the `target` argument to `extract`. The function will always return a list of matching items of the specified type. If no target type is provided, `extract` will return a list of strings.

To extract multiple types in one call, use a `Union` (or `|` in Python 3.10+). Here's a simple example for combining float and int values, but you could do the same for any other types:

Expand Down
3 changes: 2 additions & 1 deletion docs/ai/text/generation.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ The `generate` function is the primary tool for generating synthetic data. It ac

`generate` supports almost all builtin Python types, plus Pydantic models, Python's `Literal`, and `TypedDict`. Pydantic models are especially useful for specifying specific features of the generated data, such as locations, dates, or more complex types. Builtin types are most useful in conjunction with instructions that provide more precise criteria for generation.

To specify the output type, pass it as the `target` argument to `generate`. Generate will always return a list of `n` items of the specified type. If no target is provided, `generate` will return a list of strings.
To specify the output type, pass it as the `target` argument to `generate`. The function will always return a list of `n` items of the specified type. If no target is provided, `generate` will return a list of strings.


!!! warning "Avoid tuples"
OpenAI models currently have trouble parsing the API representation of tuples. Therefore we recommend using lists or Pydantic models (for more strict typing) instead. Tuple support will be added in a future release.
Expand Down
4 changes: 4 additions & 0 deletions docs/static/css/custom.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
/* color themes */

/* Set header color without changing whole theme */
.md-header, .md-tabs {
background-color: var(--marvin-blue);
}

/* Defaults for images */
.md-typeset img {
Expand Down
3 changes: 0 additions & 3 deletions docs/static/css/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
--md-primary-fg-color: var(--marvin-blue);
}

article a {
text-decoration: underline !important;
}

.md-main__inner {
margin-top: 8px !important;
Expand Down
169 changes: 87 additions & 82 deletions docs/welcome/what_is_marvin.md
Original file line number Diff line number Diff line change
@@ -1,144 +1,149 @@
# What is Marvin?

Marvin is a Python library that lets you use Large Language Models by writing code, not prompts. It's open source,
free to use, rigorously type-hinted, used by thousands of engineers, and built by the engineering team at [Prefect](https://prefect.io).

Marvin is a lightweight AI toolkit for building natural language interfaces that are reliable, scalable, and easy to trust.

??? Question "Explain like I'm 5"
=== "I'm a technical 5-year-old"
Each of Marvin's tools is simple and self-documenting, using AI to solve common but complex challenges like entity extraction, classification, and generating synthetic data. Each tool is independent and incrementally adoptable, so you can use them on their own or in combination with any other library. Marvin is also multi-modal, supporting both image and audio generation as well using images as inputs for extraction and classification.

Marvin lets your software speak English and ask questions to Large Language Models.

It introspects the types and docstrings of your functions and data models, and automatically renders them
as prompts for an LLM. You write code as you would normally,
rather than prompts, and Marvin handles the back-and-forth translation.

This lets you focus on what you've always focused on: writing clean, versioned, reusable *code* and *data models*, and not scrutinizing whether you begged your LLM hard enough to output JSON or needed to offer it a bigger tip for the right answer.

Extracting, generating, cleaning, or classifying data is as simple as writing a function or a data model.
Marvin is for developers who care more about *using* AI than *building* AI, and we are focused on creating an exceptional developer experience. Marvin users should feel empowered to bring tightly-scoped "AI magic" into any traditional software project with just a few extra lines of code.

=== "I'm not technical"
Marvin aims to merge the best practices for building dependable, observable software with the best practices for building with generative AI into a single, easy-to-use library. It's a serious tool, but we hope you have fun with it.

Marvin lets engineers who know Python use Large Language Models without needing to write prompts.
Marvin is open-source, free to use, and made with 💙 by the team at [Prefect](https://www.prefect.io/).

It turns out that ChatGPT and other Large Language Models are good at performing boring but incredibly valuable
business-critical tasks beyond being a chatbot: you can use them to classify emails as spam, extract key figures
from a report - exactly however you want for your scenario. When you use something like ChatGPT you spend a lot of time crafting the right prompt or
context to get it to write your email, plan your date night, etc.
If you want your software to use ChatGPT, you need to let it turn its objective into English. Marvin handles this
'translation' for you, so you get to just write code like you normally would. Engineers like using Marvin because it
lets them write software like they're used to.
Simply put, it lets you use Generative AI without feeling like you have to learn a framework.

!!! Example "What's it like to use Marvin?"

Marvin is lightweight and is built for incremental adoption. You can use it purely as a serialization library and bring your own stack, or use its engine to work with any OpenAI framework.
=== "Classify text"

!!! Example "How does it feel?"

=== "Classification"

Marvin can classify text against a set of labels, optionally taking instructions for more control.
Classify any text against a set of labels:

```python
import marvin

marvin.classify('I love this library!', labels=['positive', 'negative'])
# "positive"


marvin.classify(
"I need to pick up my prescription",
labels=["Store Hours", "Pharmacy", "Returns"],
instructions="Classify the customer's intent",
result = marvin.classify(
"Marvin is so easy to use!",
labels=["positive", "negative"],
)
# "Pharmacy"

```

=== "Type coercion"
Marvin can convert text to a Python type or Pydantic model.
!!! success "Result"
```python
assert result == "positive"
```

=== "Extract entities"

Extract product features from user feedback:

```python
import marvin
from pydantic import BaseModel

features = marvin.extract(
"I love my new phone's camera, but the battery life could be improved.",
instructions="product features",
)
```

marvin.cast('nyc', to=str, instructions='Standardize the location as city and state')
# "New York, NY"
!!! success "Result"
```python
assert features == ['camera', 'battery life']
```

=== "Standardize inputs"
Convert natural language to a structured form:

marvin.cast('one, two, three', to=list[int])
# [1, 2, 3]
```python hl_lines="10"
import marvin
from pydantic import BaseModel, Field


class Location(BaseModel):
city: str
state: str
state: str = Field(description='2-letter abbreviation')


marvin.cast('nyc', Location)
# Location(city="New York", state="NY")
result = marvin.cast('the big apple', Location)
```

!!! success "Result"
```python
assert result == Location(city="New York", state="NY")
```


=== "Structured data"
Marvin's AI models allow any Pydantic model to be instantiated from text.
=== "Generate data"
Generate synthetic data from a schema and instructions:

```python
```python hl_lines="10-14"
import marvin
from pydantic import BaseModel
from pydantic import BaseModel, Field


@marvin.model
class Location(BaseModel):
city: str
state: str
latitude: float
longitude: float
state: str = Field(description='2-letter abbreviation')


Location("They say they're from the Windy City!")
# Location(city='Chicago', state='Illinois', latitude=41.8781, longitude=-87.6298)
result = marvin.generate(
n=4,
target=Location,
instructions='US cities named after presidents',
)
```
Notice there's no code written, just the expected types. Marvin's components turn your function into a prompt, uses AI to get its most likely output, and parses its response.


=== "Custom transformations"
!!! success "Result"
```python
assert result == [
Location(city="Washington", state="DC"),
Location(city="Jefferson City", state="MO"),
Location(city="Lincoln", state="NE"),
Location(city="Madison", state="WI"),
]
```

=== "Custom AI functions"

Marvin functions let you combine any inputs, instructions, and output types to create custom AI-powered behaviors.

```python
```python hl_lines="3"
import marvin


@marvin.fn
def list_fruits(n: int, color: str = 'red') -> list[str]:
"""Generates a list of `n` `color` fruits"""

def list_fruits(n: int, color: str) -> list[str]:
"""Generates a list of `n` fruits that are `color`"""

list_fruits(3)
# "['Apple', 'Cherry', 'Strawberry']"
fruits = list_fruits(3, color='red')
```
Notice `list_fruits` has no code. Marvin's components turn your function into a prompt, ask AI for its most likely output, and parses its response.

!!! success "Result"
```python
assert fruits == ["apple", "cherry", "strawberry"]
```

Note that `list_fruits` has no source code. Marvin's components turn your function into a prompt, ask AI for its most likely output, and parses its response.
For years we've built open source software used by tens of thousands of data and machine learning engineers daily. Marvin brings those best practices for building dependable, observable software to generative AI.

## What models do we support?
??? Question "Explain Marvin like I'm 5"
=== "(I'm a technical 5-year-old)"

Marvin supports the full suite of OpenAI models, and should be compatible with any model that adheres to the OpenAI spec. It's the easiest way to use Function Calling and Tool use. We run (and foot the bill for!) a public evaluation test suite to ensure that our library does what we say it does. If you're a community member who wants to build an maintain an integration with another provider, get in touch.
Marvin lets your software speak English and ask questions to Large Language Models.

Note that Marvin can be used as a serialization library, so you can bring your own Large Language Models and exclusively use Marvin to generate prompts from your code.
It introspects the types and docstrings of your functions and data models, and automatically renders them as prompts for an LLM. You write code as you would normally, rather than prompts, and Marvin handles the back-and-forth translation.

## Why are we building Marvin?
This lets you focus on what you've always focused on: writing clean, versioned, reusable *code* and *data models*, and not scrutinizing whether you begged your LLM hard enough to output JSON or needed to offer it a bigger tip for the right answer.

At Prefect we support thousands of engineers in workflow orchestration, from small startups to huge enterprise. In late 2022 we started working with our community to adopt AI into their workflows and found there wasn't a sane option for teams looking to build simply, quickly, and durably with generative AI.
Extracting, generating, cleaning, or classifying data is as simple as writing a function or a data model.

## Why Marvin over alternatives?
=== "(I'm not technical)"

Marvin's built and maintained by the team at Prefect. We work with thousands of engineers daily and work backwards from their experiences to build reliable, intuitive and pleasant interfaces to otherwise hard things.
Marvin lets engineers who know Python use Large Language Models without needing to write prompts.

There's a whole fleet of frameworks to work with Large Language Models, but we're not smart enough to understand them. We try to fight abstractions wherever we can so that users can easily understand and customize what's going on.
It turns out that ChatGPT and other Large Language Models are good at performing boring but incredibly valuable business-critical tasks beyond being a chatbot: you can use them to classify emails as spam, extract key figures from a report - exactly however you want for your scenario. When you use something like ChatGPT you spend a lot of time crafting the right prompt or context to get it to write your email, plan your date night, etc.
If you want your software to use ChatGPT, you need to let it turn its objective into English. Marvin handles this 'translation' for you, so you get to just write code like you normally would. Engineers like using Marvin because it lets them write software like they're used to.
Simply put, it lets you use Generative AI without feeling like you have to learn a framework.

5 changes: 4 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ repo_url: https://github.com/prefecthq/marvin

nav:
- Docs:

- welcome/what_is_marvin.md

- Getting started:
- welcome/installation.md
- welcome/quickstart.md
Expand Down Expand Up @@ -89,7 +91,8 @@ theme:
- content.code.select
- content.code.annotate
palette:
primary: custom
primary: blue
accent: teal
name: material
custom_dir: docs/overrides
logo: assets/images/logos/askmarvin_mascot.jpeg
Expand Down
12 changes: 10 additions & 2 deletions src/marvin/ai/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ def cast(

def extract(
data: str,
target: type[T],
target: type[T] = None,
instructions: Optional[str] = None,
model_kwargs: Optional[dict] = None,
client: Optional[MarvinClient] = None,
Expand All @@ -288,9 +288,13 @@ def extract(
specified type from the input data. The extracted entities are returned as a
list.
Note that *either* a target type or instructions must be provided (or both).
If only instructions are provided, the target type is assumed to be a
string.
Args:
data (str): The data from which to extract entities.
target (type): The type of entities to extract.
target (type, optional): The type of entities to extract.
instructions (str, optional): Specific instructions for the extraction.
Defaults to None.
model_kwargs (dict, optional): Additional keyword arguments for the
Expand All @@ -300,6 +304,10 @@ def extract(
Returns:
list: A list of extracted entities of the specified type.
"""
if target is None and instructions is None:
raise ValueError("Must provide either a target type or instructions.")
elif target is None:
target = str
model_kwargs = model_kwargs or {}
return _generate_typed_llm_response_with_tool(
prompt_template=EXTRACT_PROMPT,
Expand Down

0 comments on commit f483ab2

Please sign in to comment.