Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.0 component refactor #721

Merged
merged 15 commits into from
Jan 5, 2024
4 changes: 2 additions & 2 deletions cookbook/flows/github_digest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import httpx
import marvin
from marvin import ai_fn
from marvin import fn
from marvin.utilities.strings import jinja_env
from prefect import flow, task
from prefect.artifacts import create_markdown_artifact
Expand Down Expand Up @@ -47,7 +47,7 @@
) # noqa: E501


@ai_fn
@fn
async def summarize_digest(markdown_digest: str) -> str:
"""Produce a short story based on the GitHub digest.

Expand Down
5 changes: 3 additions & 2 deletions cookbook/maze.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
import random
from enum import Enum
from io import StringIO
from typing import Literal

from marvin.beta.applications import AIApplication
from pydantic import BaseModel
from rich.console import Console
from rich.table import Table
from typing_extensions import Literal

GAME_INSTRUCTIONS = """
This is a TERROR game. You are the disembodied narrator of a maze. You've hidden a key somewhere in the
Expand Down Expand Up @@ -205,7 +205,8 @@ def move(self, direction: CardinalDirection) -> str:
if move_monster := random.random() < 0.4:
self.shuffle_monster()
return (
f"User moved {direction} and is now at {self.user_location}.\n{self.render()}"
f"User moved {direction} and is now at"
f" {self.user_location}.\n{self.render()}"
f"\nThe user may move in any of the following {self.movable_directions()!r}"
f"\n{'The monster moved somewhere.' if move_monster else ''}"
)
Expand Down
4 changes: 2 additions & 2 deletions cookbook/slackbot/keywords.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from marvin import ai_fn
from marvin import fn
from marvin.utilities.slack import post_slack_message
from prefect import task
from prefect.blocks.system import JSON, Secret, String
Expand Down Expand Up @@ -36,7 +36,7 @@ async def get_reduced_kw_relationship_map() -> dict:
}


@ai_fn
@fn
def activation_score(message: str, keyword: str, target_relationship: str) -> float:
"""Return a score between 0 and 1 indicating whether the target relationship exists
between the message and the keyword"""
Expand Down
4 changes: 2 additions & 2 deletions cookbook/slackbot/parent_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from contextlib import asynccontextmanager

from fastapi import FastAPI
from marvin import ai_fn
from marvin import fn
from marvin.beta.applications import AIApplication
from marvin.beta.applications.state.json_block import JSONBlockState
from marvin.beta.assistants import Assistant
Expand All @@ -28,7 +28,7 @@ class Lesson(TypedDict):
heuristic: str | None


@ai_fn(model="gpt-3.5-turbo-1106")
@fn(model="gpt-3.5-turbo-1106")
def take_lesson_from_interaction(
transcript: str,
assistant_instructions: str,
Expand Down
2 changes: 1 addition & 1 deletion docs/api_reference/components/ai_classifier.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
::: marvin.components.ai_classifier
::: marvin.components.classifier
1 change: 0 additions & 1 deletion docs/api_reference/components/ai_function.md

This file was deleted.

1 change: 0 additions & 1 deletion docs/api_reference/components/ai_model.md

This file was deleted.

1 change: 1 addition & 0 deletions docs/api_reference/components/functions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: marvin.components.function
1 change: 1 addition & 0 deletions docs/api_reference/components/models.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: marvin.components.model
2 changes: 1 addition & 1 deletion docs/api_reference/index.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Sections

## Components
- [AI Classifiers](/api_reference/components/ai_classifier/)
- [AI Classifiers](/api_reference/components/classifier/)
- [AI Functions](/api_reference/components/ai_function/)
- [AI Models](/api_reference/components/ai_model/)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ AI Classifiers are a high-level component, or building block, of Marvin. Like al
<div class="admonition abstract">
<p class="admonition-title">What it does</p>
<p>
<code>@ai_classifier</code> is a decorator that lets you use LLMs to choose options, tools, or classify input.
<code>@classifier</code> is a decorator that lets you use LLMs to choose options, tools, or classify input.
</p>
</div>

!!! example
```python
from marvin import ai_classifier
from marvin import classifier
from enum import Enum

class CustomerIntent(Enum):
Expand All @@ -26,7 +26,7 @@ AI Classifiers are a high-level component, or building block, of Marvin. Like al
ACCOUNT_CANCELLATION = 'ACCOUNT_CANCELLATION'
OPERATOR_CUSTOMER_SERVICE = 'OPERATOR_CUSTOMER_SERVICE'

@ai_classifier
@classifier
def classify_intent(text: str) -> CustomerIntent:
'''Classifies the most likely intent from user input'''

Expand Down Expand Up @@ -67,15 +67,15 @@ AI Classifiers are a high-level component, or building block, of Marvin. Like al
## Features
#### 🚅 Bulletproof

`ai_classifier` will always output one of the options you've given it
`classifier` will always output one of the options you've given it


```python
from marvin import ai_classifier
from marvin import classifier
from enum import Enum


@ai_classifier
@classifier
class AppRoute(Enum):
"""Represents distinct routes command bar for a different application"""

Expand All @@ -102,8 +102,8 @@ AppRoute("update my name")

#### 🏃 Fast

`ai_classifier` only asks your LLM to output one token, so it's blazing fast - on the order of ~200ms in testing.
`classifier` only asks your LLM to output one token, so it's blazing fast - on the order of ~200ms in testing.

#### 🫡 Deterministic

`ai_classifier` will be deterministic so long as the underlying model and options does not change.
`classifier` will be deterministic so long as the underlying model and options does not change.
File renamed without changes.
2 changes: 1 addition & 1 deletion docs/components/ai_model.md → docs/components/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ CapTable("""\
import datetime
from typing import List
from pydantic import BaseModel
from typing_extensions import Literal
from typing import Literal
from marvin import ai_model


Expand Down
12 changes: 6 additions & 6 deletions docs/components/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,10 @@ AI Classifiers let you build multi-label classifiers with no code and no trainin

!!! example "Example"
=== "As a decorator"
`ai_classifier` can decorate python functions whose return annotation is an `Enum` or `Literal`. The prompt is tuned for classification tasks,
`classifier` can decorate python functions whose return annotation is an `Enum` or `Literal`. The prompt is tuned for classification tasks,
and uses a form of `constrained sampling` to make guarantee a fast valid choice.
```python
from marvin import ai_classifier
from marvin import classifier
from enum import Enum

class AppRoute(Enum):
Expand All @@ -283,7 +283,7 @@ AI Classifiers let you build multi-label classifiers with no code and no trainin
PROJECTS = "/projects"
WORKSPACES = "/workspaces"

@ai_classifier(client = client)
@classifier(client = client)
def classify_intent(text: str) -> AppRoute:
'''Classifies user's intent into most useful route'''

Expand Down Expand Up @@ -329,7 +329,7 @@ AI Classifiers let you build multi-label classifiers with no code and no trainin

=== "As a function"
```python
from marvin import ai_classifier
from marvin import classifier
from enum import Enum

class AppRoute(Enum):
Expand All @@ -348,12 +348,12 @@ AI Classifiers let you build multi-label classifiers with no code and no trainin
def classify_intent(text: str) -> AppRoute:
'''Classifies user's intent into most useful route'''

ai_classifier(classify_intent, client = client)("update my name")
classifier(classify_intent, client = client)("update my name")
```
??? info "Generated Prompt"
You can view and/or eject the generated prompt by simply calling
```python
ai_classifier(classify_intent, client = client).as_prompt("update my name").serialize()
classifier(classify_intent, client = client).as_prompt("update my name").serialize()
```
When you do you'll see the raw payload that's sent to the LLM. The prompt you send is fully customizable.
```json
Expand Down
4 changes: 2 additions & 2 deletions docs/welcome/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ or fully use its engine to work with OpenAI and other providers.
Marvin exposes a number of high level components to simplify working with AI.

```python
from marvin import ai_classifier
from marvin import classifier
from typing import Literal

@ai_classifier
@classifier
def customer_intent(text: str) -> Literal['Store Hours', 'Pharmacy', 'Returns']:
"""Classifies incoming customer intent"""

Expand Down
14 changes: 7 additions & 7 deletions docs/welcome/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ After [installing Marvin](../installation), the fastest way to get started is by
MARVIN_OPENAI_ORGANIZATION=org-xxx
```

- Pass your API Key to Marvin's `OpenAI` client constructor and pass it to Marvin's `ai_fn`, `ai_classifier`, or `ai_model` decorators.
- Pass your API Key to Marvin's `OpenAI` client constructor and pass it to Marvin's `ai_fn`, `classifier`, or `ai_model` decorators.

```python
from marvin import ai_fn
Expand Down Expand Up @@ -233,10 +233,10 @@ AI Classifiers let you build multi-label classifiers with no code and no trainin

!!! example "Example"
=== "As a decorator"
`ai_classifier` can decorate python functions whose return annotation is an `Enum` or `Literal`. The prompt is tuned for classification tasks,
`classifier` can decorate python functions whose return annotation is an `Enum` or `Literal`. The prompt is tuned for classification tasks,
and uses a form of `constrained sampling` to make guarantee a fast valid choice.
```python
from marvin import ai_classifier
from marvin import classifier
from enum import Enum

class AppRoute(Enum):
Expand All @@ -252,7 +252,7 @@ AI Classifiers let you build multi-label classifiers with no code and no trainin
PROJECTS = "/projects"
WORKSPACES = "/workspaces"

@ai_classifier(client = client)
@classifier(client = client)
def classify_intent(text: str) -> AppRoute:
'''Classifies user's intent into most useful route'''

Expand Down Expand Up @@ -298,7 +298,7 @@ AI Classifiers let you build multi-label classifiers with no code and no trainin

=== "As a function"
```python
from marvin import ai_classifier
from marvin import classifier
from enum import Enum

class AppRoute(Enum):
Expand All @@ -317,12 +317,12 @@ AI Classifiers let you build multi-label classifiers with no code and no trainin
def classify_intent(text: str) -> AppRoute:
'''Classifies user's intent into most useful route'''

ai_classifier(classify_intent, client = client)("update my name")
classifier(classify_intent, client = client)("update my name")
```
??? info "Generated Prompt"
You can view and/or eject the generated prompt by simply calling
```python
ai_classifier(classify_intent, client = client).as_prompt("update my name").serialize()
classifier(classify_intent, client = client).as_prompt("update my name").serialize()
```
When you do you'll see the raw payload that's sent to the LLM. The prompt you send is fully customizable.
```json
Expand Down
4 changes: 2 additions & 2 deletions docs/welcome/what_is_marvin.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ or fully use its engine to work with OpenAI and other providers.
Marvin exposes a number of high level components to simplify working with AI.

```python
from marvin import ai_classifier
from marvin import classifier
from typing import Literal

@ai_classifier
@classifier
def customer_intent(text: str) -> Literal['Store Hours', 'Pharmacy', 'Returns']:
"""Classifies incoming customer intent"""

Expand Down
6 changes: 3 additions & 3 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ nav:

- Components:
- Overview: components/overview.md
- AI Function: components/ai_function.md
- Function: components/functions.md
- AI Model: components/ai_model.md
- AI Classifier: components/ai_classifier.md
- Classifier: components/ai_classifier.md
- AI Application: components/ai_application.md

- Examples:
Expand All @@ -35,7 +35,7 @@ nav:
- api_reference/index.md
- AI Components:
- ai_classifier: api_reference/components/ai_classifier.md
- ai_function: api_reference/components/ai_function.md
- function: api_reference/components/functions.md
- ai_model: api_reference/components/ai_model.md
- Settings:
- settings: api_reference/settings.md
Expand Down
18 changes: 13 additions & 5 deletions src/marvin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from .settings import settings

# legacy
from .components import ai_fn, ai_model, ai_classifier
from .components import fn, image, speech, model, cast, extract, classify
from .components.prompt.fn import prompt_fn

try:
Expand All @@ -10,9 +9,18 @@
__version__ = "unknown"

__all__ = [
"ai_fn",
"ai_model",
"ai_classifier",
"fn",
"image",
"model",
"cast",
"extract",
"classify",
"speech",
"prompt_fn",
"settings",
]


# compatibility with Marvin v1
from .components import fn as ai_fn, model as ai_model
from .components.classifier import classifier as ai_classifier
3 changes: 1 addition & 2 deletions src/marvin/_mappings/types.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from enum import Enum
from types import GenericAlias
from typing import Any, Callable, Optional, Union, get_args, get_origin
from typing import Any, Callable, Literal, Optional, Union, get_args, get_origin

from pydantic import BaseModel, create_model
from pydantic.fields import FieldInfo
from typing_extensions import Literal

from marvin.requests import Grammar, Tool, ToolSet
from marvin.settings import settings
Expand Down
6 changes: 3 additions & 3 deletions src/marvin/ai.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from marvin.client.openai import paint, speak
from marvin.components.ai_classifier import ai_classifier as classifier
from marvin.components.ai_function import ai_fn as fn
from marvin.components.ai_model import ai_model as model
from marvin.components.classifier import classifier
from marvin.components.function import fn
from marvin.components.model import model

__all__ = ["speak", "fn", "model", "speak", "paint", "classifier"]
2 changes: 1 addition & 1 deletion src/marvin/beta/applications/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .applications import AIApplication
from .applications import Application
Loading