Skip to content

Commit

Permalink
Updating tutorial
Browse files Browse the repository at this point in the history
  • Loading branch information
jlowin committed Jan 16, 2024
1 parent 84f788a commit 4337ee5
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 32 deletions.
4 changes: 4 additions & 0 deletions docs/welcome/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ Upgrade to the latest released version at any time:
pip install marvin -U
```

## Tutorial

Now that you've installed Marvin, check out the [tutorial](tutorial.md) to learn how to use it.

## Requirements

Marvin requires Python 3.9 or greater, and is tested on all major Python versions and operating systems.
Expand Down
2 changes: 2 additions & 0 deletions docs/welcome/quickstart.md → docs/welcome/quickstart_old.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Quickstart

0-60 in 60 seconds.

After [installing Marvin](../installation), the fastest way to get started is by using one of Marvin's high-level [AI components](../../components/overview). These components are designed to integrate AI into abstractions you already know well, creating the best possible opt-in developer experience.

!!! info "Initializing a Client"
Expand Down
173 changes: 173 additions & 0 deletions docs/welcome/tutorial.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# Tutorial

![](/docs/assets/images/heroes/dont_panic.png){ width=500 }

## Installing Marvin

Before we can start, you'll need to [install Marvin](installation.md). Come back here when you're done!

(Spoiler alert: run `pip install marvin -U`.)

## Getting an OpenAI API Key

Marvin uses OpenAI models to power all of its tools. In order to use Marvin, you'll need an OpenAI API key.

You can create an API key [on the OpenAI platform ](https://platform.openai.com/api-keys). Once you've created it, set it as an environment variable called `OPENAI_API_KEY` (for any application on your machine to use) or `MARVIN_OPENAI_API_KEY` (if you only want Marvin to use it). In addition to setting it in your terminal, you can also write the variable to a dotenv file at `~/.marvin/.env`.

For quick use, you can also pass your API key directly to Marvin at runtime. We do **NOT** recommend this for production:

```python
import marvin
marvin.settings.openai.api_key = 'YOUR_API_KEY'
```

## Tools

Marvin has a variety of tools that let you use LLMs to solve common but complex problems. In this tutorial, we'll try out a few of them to get a feel for how Marvin works. By the end of the tutorial, you'll have tried some of Marvin's advanced features and be ready to take on the universe! Just don't forget your towel.

### 🏷️ Classification

Classification is one of Marvin's most straightforward features. Given some text and a list of labels, Marvin will choose the label that best fits the text. The `classify` function is great for tasks like sentiment analysis, intent classification, routing, and more.

!!! Example "True/False"
The simplest possible classification example maps the word "yes" to a boolean value like `True` or `False`:

```python
import marvin

result = marvin.classify("yes", labels=bool)
```

!!! success "Result"
```python
assert result is True
```

Now that you've seen the most basic example, let's try something a little more useful:

!!! Example "Sentiment"

This example performs a basic sentiment analysis on some text:

```python
import marvin

result = marvin.classify(
"Marvin is so easy to use!",
labels=["positive", "negative"],
)
```

!!! success "Result"
```python
assert result == "positive"
```

This is a great example of how all Marvin tools should feel. Historically, classifying text was a major challenge for natural language processing frameworks. But with Marvin, it's as easy as calling a function.

!!! tip "Structured labels"
For the `classify` function, you can supply labels as a `list` of labels, a `bool` type, an `Enum` class, or a `Literal` type. This gives you many options for returning structured (non-string) labels.

### 🪄 Transformation

Classification maps text to a single label, but what if you want to convert text to a more structured form? Marvin's `cast` function lets you do just that. Given some text and a target type, Marvin will return a structured representation of the text.


!!! example "Standardization"

Suppose you ran a survey and one of the questions asked where people live. Marvin can convert their freeform responses to a structured `Location` type:

```python
import marvin
from pydantic import BaseModel

class Location(BaseModel):
city: str
state: str

location = marvin.cast("NYC", target=Location)
```

!!! success "Result"
The string "NYC" was converted to a full `Location` object:

```python
assert location == Location(city="New York", state="New York")
```

#### Instructions

All Marvin functions have an `instructions` parameter that let you fine-tune their behavior with natural language. For example, you can use instructions to tell Marvin to extract a specific type of information from a text or to format a response in a specific way.

Suppose you wanted to standardize the survey responses in the previous example, but instead of using a full Pydantic model, you wanted the result to still be a string. The `cast` function will accept `target=str`, but that's so general it's unlikely to do what you want without additional guidance. That's where instructions come in:

!!! example "Instructions"

Repeat the previous example, but cast to a string according to the instructions:

```python
import marvin

location = marvin.cast(
"NYC",
target=str,
instructions="Return the proper city and state name",
)
```

!!! success "Result"
The result is a string that complies with the instructions:

```python
assert location == "New York, New York"
```

### 🔍 Extraction

The `extract` function is like a generalization of the `cast` function: instead of transforming the entire text to a single target type, it extracts a list of entities from the text. This is useful for identifying people, places, ratings, keywords, and more.

!!! Example "Extraction"

Suppose you wanted to extract the product features mentioned in a review:

```python
import marvin

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

!!! success "Result"
```python
assert features == ["camera", "battery life"]
```

The `extract` function can take a target type, just like `cast`. This lets you extract structured entities from text. For example, you could extract a list of `Location` objects from a text:

!!! Example "Extract locations"

```python
import marvin
from pydantic import BaseModel

class Location(BaseModel):
city: str
state: str

locations = marvin.extract(
"They've got a game in NY, then they go to DC before Los Angeles.",
target=Location
)
```

!!! success "Result"
```python
assert locations == [
Location(city="New York", state="New York"),
Location(city="Washington", state="District of Columbia"),
Location(city="Los Angeles", state="California"),
]
```

4 changes: 2 additions & 2 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ nav:
- welcome/what_is_marvin.md

- Getting started:
- welcome/installation.md
- welcome/quickstart.md
- Installation: welcome/installation.md
- Tutorial: welcome/tutorial.md
# - help/legacy_docs.md

# - Overview: welcome/overview.md
Expand Down
37 changes: 25 additions & 12 deletions src/marvin/client/openai.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import inspect
from functools import partial
from pathlib import Path
from typing import (
Expand Down Expand Up @@ -156,25 +157,37 @@ def _get_default_client(client_type: str) -> Union[Client, AsyncClient]:
)
except AttributeError:
raise ValueError(
"To use Azure OpenAI, please set all of the following environment"
" variables in `~/.marvin/.env`:"
"\n\n"
"```"
"\nMARVIN_USE_AZURE_OPENAI=true"
"\nMARVIN_AZURE_OPENAI_API_KEY=..."
"\nMARVIN_AZURE_OPENAI_API_VERSION=..."
"\nMARVIN_AZURE_OPENAI_ENDPOINT=..."
"\nMARVIN_AZURE_OPENAI_DEPLOYMENT_NAME=..."
"\n```"
inspect.cleandoc(
"""
To use Azure OpenAI, please set all of the following environment variables in `~/.marvin/.env`:
```
MARVIN_USE_AZURE_OPENAI=true
MARVIN_AZURE_OPENAI_API_KEY=...
MARVIN_AZURE_OPENAI_API_VERSION=...
MARVIN_AZURE_OPENAI_ENDPOINT=...
MARVIN_AZURE_OPENAI_DEPLOYMENT_NAME=...
```
"""
)
)

api_key = (
settings.openai.api_key.get_secret_value() if settings.openai.api_key else None
)
if not api_key:
raise ValueError(
"OpenAI API key not found. Please either set `MARVIN_OPENAI_API_KEY` in"
" `~/.marvin/.env` or otherwise set `OPENAI_API_KEY` in your environment."
inspect.cleandoc(
"""
OpenAI API key not found! Marvin will not work properly without it.
You can either:
1. Set the `MARVIN_OPENAI_API_KEY` or `OPENAI_API_KEY` environment variables
2. Set `marvin.settings.openai.api_key` in your code (not recommended for production)
If you do not have an OpenAI API key, you can create one at https://platform.openai.com/api-keys.
"""
)
)
if client_type not in ["sync", "async"]:
raise ValueError(f"Invalid client type {client_type!r}")
Expand Down
22 changes: 4 additions & 18 deletions src/marvin/settings.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,4 @@
"""Settings for configuring `marvin`.
## Requirements
All you ***need*** to configure is your OpenAI API key.
You can set this in `~/.marvin/.env` or as an environment variable on your system:
```
MARVIN_OPENAI_API_KEY=sk-...
```
---
"""
"""Settings for configuring `marvin`."""

import os
from contextlib import contextmanager
Expand Down Expand Up @@ -188,13 +178,9 @@ class OpenAISettings(MarvinSettings):
@field_validator("api_key")
def discover_api_key(cls, v):
if v is None:
v = SecretStr(os.environ.get("OPENAI_API_KEY"))
if v.get_secret_value() is None:
raise ValueError(
"OpenAI API key not found. Please either set"
" `MARVIN_OPENAI_API_KEY` in `~/.marvin/.env` or otherwise set"
" `OPENAI_API_KEY` in your environment."
)
# check global OpenAI API key
v = os.environ.get("OPENAI_API_KEY")

return v


Expand Down

0 comments on commit 4337ee5

Please sign in to comment.