Skip to content

Commit

Permalink
Spring cleaning
Browse files Browse the repository at this point in the history
  • Loading branch information
olokobayusuf committed Aug 21, 2024
1 parent c4306c6 commit aee116a
Show file tree
Hide file tree
Showing 23 changed files with 196 additions and 522 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/edge.yml → .github/workflows/fxnc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ jobs:

- uses: actions/setup-python@v2
with:
python-version: '3.8'
python-version: "3.11"

- name: Install dependencies
run: |
python3 -m pip install --upgrade pip
python3 -m pip install build twine
python3 -m pip install -r requirements.txt
- name: Pull EdgeFunction
run: python3 edgefxn.py
- name: Pull Function C
run: python3 fxnc.py

- name: Build Function
run: python3 -m build
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ jobs:
python3 -m pip install build twine
python3 -m pip install -r requirements.txt
- name: Pull EdgeFunction
run: python3 edgefxn.py
- name: Pull Function C
run: python3 fxnc.py

- name: Build Function
run: python3 -m build
Expand Down
24 changes: 23 additions & 1 deletion Changelog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,28 @@
## 0.0.36
+ Added `Acceleration.Default` enumeration constant.
+ Added `Acceleration.GPU` enumeration constant for running predictions on the GPU.
+ Added `Acceleration.NPU` enumeration constant forn running predictions on the neural processor.
+ Fixed crash when using `PIL.Image` values returned by edge predictors.
+ Updated to Function C 0.0.23.
+ Updated to Function C 0.0.26.
+ Removed `Value` type.
+ Removed `PredictorType` enumeration.
+ Removed `fxn.predictors.create` method for creating predictors. [Apply](https://fxn.ai/waitlist) for early access to the new experience.
+ Removed `fxn.predictions.to_object` method.
+ Removed `fxn.predictions.to_value` method.
+ Removed `Predictor.type` field.
+ Removed `Predictor.acceleration` field.
+ Removed `Prediction.type` field.
+ Removed `Acceleration.A40` enumeration constant.
+ Removed `Acceleration.A100` enumeration constant.
+ Removed `fxn create` CLI function.
+ Removed `fxn delete` CLI function.
+ Removed `fxn list` CLI function.
+ Removed `fxn search` CLI function.
+ Removed `fxn retrieve` CLI function.
+ Removed `fxn archive` CLI function.
+ Removed `fxn env` CLI function group.
+ Removed `--raw-outputs` option from `fxn predict` CLI function.
+ Function now requires Python 3.10+.

## 0.0.35
+ Updated to Function C 0.0.18.
Expand Down
26 changes: 9 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

[![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fdiscord.com%2Fapi%2Finvites%2Fy5vwgXkz2f%3Fwith_counts%3Dtrue&query=%24.approximate_member_count&logo=discord&logoColor=white&label=Function%20community)](https://fxn.ai/community)

Run AI prediction functions (a.k.a "predictors") in your Python apps. With Function, you can build AI-powered apps by creating and composing GPU-accelerated predictors that run in the cloud. In a few steps:
Run prediction functions (a.k.a "predictors") locally in your Python apps, with full GPU acceleration and zero dependencies. In a few steps:

## Installing Function
Function is distributed on PyPi. This distribution contains both the Python client and the command line interface (CLI). To install, open a terminal and run the following command:
Expand All @@ -22,27 +22,24 @@ Head over to [fxn.ai](https://fxn.ai) to create an account by logging in. Once y
![generate access key](https://raw.githubusercontent.com/fxnai/.github/main/access_key.gif)

## Making a Prediction
Let's run the [`@samples/stable-diffusion`](https://fxn.ai/@samplefxn/stable-diffusion) predictor which accepts a text `prompt` and generates a corresponding image. Run the following Python script:
Let's run the [`@fxn/greeting`](https://fxn.ai/@fxn/greeting) predictor which accepts a `name` and returns a congenial greeting. Run the following Python script:
```py
from fxn import Function

# Create the Function client
fxn = Function(access_key="<ACCESS KEY>")
fxn = Function(access_key="<Function access key>")
# Create a prediction
prediction = fxn.predictions.create(
tag="@samples/stable-diffusion",
inputs={
"prompt": "An astronaut riding a horse on Mars"
}
tag="@fxn/greeting",
inputs={ "name": "Peter" }
)
# Show the generated image
image = prediction.results[0]
image.show()
# Print the returned greeting
print(prediction.results[0])
```

> [!TIP]
> Explore public predictors [on Function](https://fxn.ai/explore) or [create your own](https://fxn.ai/waitlist).
r
## Using the Function CLI
Open up a terminal and run the following command:

Expand All @@ -51,14 +48,9 @@ Open up a terminal and run the following command:
fxn auth login <ACCESS KEY>

# Make a prediction using the Function CLI
fxn predict @samplefxn/stable-diffusion \
--prompt "An astronaut riding a horse on the moon"
fxn predict @fxn/greeting --name Peter
```

Within a few seconds, you should see a creepy-looking image pop up 😅:

![prediction](https://raw.githubusercontent.com/fxnai/.github/main/predict.gif)

___

## Useful Links
Expand Down
16 changes: 8 additions & 8 deletions fxn/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from .env import app as env_app
from .misc import cli_options
from .predict import predict
from .predictors import archive_predictor, create_predictor, delete_predictor, list_predictors, retrieve_predictor, search_predictors
from .predictors import archive_predictor, delete_predictor, list_predictors, retrieve_predictor, search_predictors
from ..version import __version__

# Define CLI
Expand All @@ -26,16 +26,16 @@

# Add subcommands
app.add_typer(auth_app, name="auth", help="Login, logout, and check your authentication status.")
app.add_typer(env_app, name="env", help="Manage predictor environment variables.")
#app.add_typer(env_app, name="env", help="Manage predictor environment variables.")

# Add top-level commands
app.command(name="create", help="Create a predictor.")(create_predictor)
app.command(name="delete", help="Delete a predictor.")(delete_predictor)
#app.command(name="create", help="Create a predictor.")(create_predictor)
#app.command(name="delete", help="Delete a predictor.")(delete_predictor)
app.command(name="predict", help="Make a prediction.", context_settings={ "allow_extra_args": True, "ignore_unknown_options": True })(predict)
app.command(name="list", help="List predictors.")(list_predictors)
app.command(name="search", help="Search predictors.")(search_predictors)
app.command(name="retrieve", help="Retrieve a predictor.")(retrieve_predictor)
app.command(name="archive", help="Archive a predictor.")(archive_predictor)
#app.command(name="list", help="List predictors.")(list_predictors)
#app.command(name="search", help="Search predictors.")(search_predictors)
#app.command(name="retrieve", help="Retrieve a predictor.")(retrieve_predictor)
#app.command(name="archive", help="Archive a predictor.")(archive_predictor)

# Run
if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion fxn/cli/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
def login (
access_key: str=Argument(..., help="Function access key.", envvar="FXN_ACCESS_KEY")
):
fxn = Function(access_key)
fxn = Function(access_key=access_key)
user = fxn.users.retrieve()
user = user.model_dump() if user else None
_set_access_key(access_key if user is not None else None)
Expand Down
7 changes: 3 additions & 4 deletions fxn/cli/predict.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@

def predict (
tag: str = Argument(..., help="Predictor tag."),
raw_outputs: bool = Option(False, "--raw-outputs", help="Output raw Function values instead of converting into plain Python values."),
context: Context = 0
):
run_async(_predict_async(tag, context=context, raw_outputs=raw_outputs))
run_async(_predict_async(tag, context=context))

async def _predict_async (tag: str, context: Context, raw_outputs: bool):
async def _predict_async (tag: str, context: Context):
with Progress(
SpinnerColumn(spinner_name="dots"),
TextColumn("[progress.description]{task.description}"),
Expand All @@ -34,7 +33,7 @@ async def _predict_async (tag: str, context: Context, raw_outputs: bool):
inputs = { context.args[i].replace("-", ""): _parse_value(context.args[i+1]) for i in range(0, len(context.args), 2) }
# Stream
fxn = Function(get_access_key())
async for prediction in fxn.predictions.stream(tag, inputs=inputs, raw_outputs=raw_outputs, return_binary_path=True):
async for prediction in fxn.predictions.stream(tag, inputs=inputs):
# Parse results
images = [value for value in prediction.results or [] if isinstance(value, Image.Image)]
prediction.results = [_serialize_value(value) for value in prediction.results] if prediction.results is not None else None
Expand Down
41 changes: 1 addition & 40 deletions fxn/cli/predictors.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@

from rich import print_json
from rich.progress import Progress, SpinnerColumn, TextColumn
from pathlib import Path
from typer import Argument, Option
from typing import List

from ..function import Function
from ..types import Acceleration, AccessMode, PredictorStatus, PredictorType
from ..types import PredictorStatus
from .auth import get_access_key

def retrieve_predictor (
Expand Down Expand Up @@ -47,43 +45,6 @@ def search_predictors (
predictors = [predictor.model_dump() for predictor in predictors]
print_json(data=predictors)

def create_predictor (
tag: str=Argument(..., help="Predictor tag."),
notebook: Path=Argument(..., help="Path to predictor notebook."),
type: PredictorType=Option(None, case_sensitive=False, help="Predictor type. This defaults to `cloud`."),
edge: bool=Option(False, "--edge", is_flag=True, help="Shorthand for `--type edge`."),
cloud: bool=Option(False, "--cloud", is_flag=True, help="Shorthand for `--type cloud`."),
access: AccessMode=Option(None, case_sensitive=False, help="Predictor access mode. This defaults to `private`."),
description: str=Option(None, help="Predictor description. This must be less than 200 characters long."),
media: Path=Option(None, help="Predictor image path."),
acceleration: Acceleration=Option(None, case_sensitive=False, help="Cloud predictor acceleration. This defaults to `cpu`."),
license: str=Option(None, help="Predictor license URL."),
env: List[str]=Option([], help="Specify a predictor environment variable."),
overwrite: bool=Option(None, "--overwrite", help="Overwrite any existing predictor with the same tag.")
):
with Progress(
SpinnerColumn(spinner_name="dots"),
TextColumn("[progress.description]{task.description}"),
transient=True
) as progress:
progress.add_task(description="Analyzing Function...", total=None)
fxn = Function(get_access_key())
type = PredictorType.Cloud if cloud else PredictorType.Edge if edge else type
environment = { e.split("=")[0].strip(): e.split("=")[1].strip() for e in env }
predictor = fxn.predictors.create(
tag=tag,
notebook=notebook,
type=type,
access=access,
description=description,
media=media,
acceleration=acceleration,
environment=environment,
license=license,
overwrite=overwrite
)
print_json(data=predictor.model_dump())

def delete_predictor (
tag: str=Argument(..., help="Predictor tag.")
):
Expand Down
19 changes: 9 additions & 10 deletions fxn/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ class Function:
users (UserService): Manage users.
predictors (PredictorService): Manage predictors.
predictions (PredictionService): Manage predictions.
environment_variables (EnvironmentVariableService): Manage predictor environment variables.
storage (StorageService): Upload and download files.
Constructor:
access_key (str): Function access key.
Expand All @@ -28,15 +26,16 @@ class Function:
users: UserService
predictors: PredictorService
predictions: PredictionService
environment_variables: EnvironmentVariableService
storage: StorageService
#environment_variables: EnvironmentVariableService
#storage: StorageService

def __init__ (self, access_key: str=None, api_url: str=None):
access_key = access_key or environ.get("FXN_ACCESS_KEY", None)
api_url = api_url or environ.get("FXN_API_URL", "https://api.fxn.ai")
self.client = GraphClient(access_key, api_url)
self.users = UserService(self.client)
self.storage = StorageService(self.client)
self.predictors = PredictorService(self.client, self.storage)
self.predictions = PredictionService(self.client, self.storage)
self.environment_variables = EnvironmentVariableService(self.client)
client = GraphClient(access_key, api_url)
storage = StorageService(client)
self.client = client
self.users = UserService(client)
self.predictors = PredictorService(client, storage)
self.predictions = PredictionService(client)
#self.environment_variables = EnvironmentVariableService(self.client)
File renamed without changes.
4 changes: 0 additions & 4 deletions fxn/libs/linux/__init__.py

This file was deleted.

4 changes: 0 additions & 4 deletions fxn/libs/macos/__init__.py

This file was deleted.

4 changes: 0 additions & 4 deletions fxn/libs/windows/__init__.py

This file was deleted.

Loading

0 comments on commit aee116a

Please sign in to comment.