Reference
This is a reference document for fal-serverless
isolated
decorator
isolated
decorator lets you define a function that will be run in isolated environment by fal-serverless. Here is a simple example:
from fal_serverless import isolated
@isolated()
def my_function():
return "Hello World"
my_function
is now what we call an isolated function. The subsequent my_function
calls, such as my_function()
, are sent to fal-serverless. This means that my_function
is not run locally, instead it's contents are sent to fal-serverless, executed there and the result is returned to the local environment.
The isolated
decorator accepts a number of arguments, that are described below.
requirements
You can provide custom requirements to your isolated functions. These requirement are installed only inside a fal-serverless environment and not in your local Python environment.
from fal_serverless import isolated
requirements = ["pyjokes"]
@isolated(requirements=requirements)
def my_function():
import pyjokes
return pyjokes.get_joke()
In the above example, it is not necessary to install the pyjokes
module locally. Providing it in a requirements
list results in fal-serverless automatically installing it in the fal-serverless environment. Note how pyjokes
is imported inside the my_function
definition. This way, the Python interpreter will not look for pyjokes
in your locally installed modules.
machine_type
Isolated functions can run on different machine types. Here's a list of currently supported machine types:
XS
: 0.25 CPU cores, 256MB RAMS
: 0.50 CPU cores, 1GB RAMM
: 2 CPU cores, 8GB RAML
: 4 CPU cores, 32GB RAMXL
: 8 CPU cores, 128GB RAMGPU-T4
: 4 CPU cores, 26GB RAM, 1 GPU core (T4, 16GB VRAM)GPU
: 8 CPU cores, 64GB RAM, 1 GPU core (A100, 40GB VRAM)
The default machine type is XS
. Machine type can be specified when defining an isolated function:
from fal_serverless import isolated
requirements = ["pyjokes"]
@isolated(requirements=requirements, machine_type="M")
def my_function():
import pyjokes
return pyjokes.get_joke()
You can also use an isolated function to define a new one with a different machine type:
my_function_L = my_function.on(machine_type="L")
In the above example, my_function_L
is a new isolated function that has the same contents as my_function
, but it will run on a machine type L
.
Both functions can be called:
my_function() # executed on machine type `M`
my_function_L() # same as my_function but executed on machine type `L`
my_function
is executed on machine type M
. And my_function_L
, which has the same logic as my_function
, is now executed on machine type L
.
Local development
Sometimes you might want to test your isolated functions locally before running them on fal-serverless. For this purpose we provided a special local
host environment. Taking my_function
from the previous example:
from fal_serverless import isolated, local
my_function_local = my_function.on(local)
my_function_local
is still an isolated function, but it will not run in fal-serverless. Instead, fal-serverless will create a dedicated isolated Python environment on your local machine and execute my_function_local
there.
The .on()
method accepts the same arguments as the isolated
decorator. So you can define a new isolated function based on my_function_local
this way:
from fal_serverless import cloud
my_function_cloud = my_function_local.on(cloud, machine_type="M")
The resulting my_function_cloud
is the same as the original my_function
. It has the same logic and it is executed on a machine type M
.
Local isolated functions can also be defined with a decorator by providing a host
argument:
from fal_serverless import isolated, local
requirements = ["pyjokes"]
@isolated(requirements=requirements, host=local)
def my_function_local2():
import pyjokes
return pyjokes.get_joke()
In this case, my_function_local
and my_function_local2
will have exactly the same behavior.
credentials
The credentials argument lets you provide key-based credentials:
from fal_serverless import isolated, CloudKeyCredentials
credentials = CloudKeyCredentials(key_id='your-key-id', key_secret='your-key-secret')
@isolated(credentials=credentials)
def my_function()
return "hello world"
More information on credentials and authentication.
keep_alive
The keep_alive
argument allows for optimization of the function execution process. It lets you specify the number of seconds that the isolated environment should be kept alive after a function execution. This means that subsequent calls to the same function can reuse the existing memory and compute resources if it's still alive, rather than provisioning new infrastructure. This can significantly reduce the time required to start up the runtime and the overall execution time of the isolated function.
By keeping the environment alive, fal-serverless minimizes the time spent on environment setup and initializations. This is especially useful for functions that are frequently called. The keep_alive feature makes it easier to run isolated functions at scale, as it helps to minimize the overhead associated with function execution.
from fal_serverless import isolated
@isolated(keep_alive=20, requirements=["pyjokes"])
def get_joke()
import pyjokes
return pyjokes.get_joke()
In the example above, isolated environment of get_joke
will be kept alive for 20 seconds. If get_joke
is called again within 20 seconds, it will reuse isolated environment and restart the keep_alive
timer.
The default value for keep_alive is 10 seconds.
cached
decorator
Functions with @cached
decorator get their output cached for improved performance. If the same cached function is called in an isolated environment and the environment has been kept alive since the last time the function was called, then the function is not executed and instead, a cached return value is returned. This can significantly reduce the time it takes to execute isolated functions and minimize the resources used.
import time
from fal_serverless import isolated, cached
@cached
def my_cached_function():
# Simulate a time-consuming calculation
time.sleep(2)
return "Hello, World!"
@isolated(keep_alive=10)
def my_isolated_function():
result = my_cached_function()
return f"The result is: {result}"
# Call the isolated function multiple times
result1 = my_isolated_function() # Takes more than 2 seconds
result2 = my_isolated_function() # Almost instant
print(result1) # Output: "The result is: Hello, World!"
print(result2) # Output: "The result is: Hello, World!"
sync_dir
Function
The sync_dir
function allows you to upload local directories to the persistent /data
directory.
Syntax
from fal_serverless import sync_dir
sync_dir(path_to_local_dir, remote_dir)
Parameters
path_to_local_dir
(str): The local path to the directory you want to upload.remote_dir
(str): The remote directory in which to store the uploaded files. This has to be an absolute directory that starts with/data
.
Return
It returns a string with remote directory location for easy usage in other isolated functions.
Usage example
Here's an example of how to use the sync_dir function:
from fal_serverless import sync_dir, isolated
# Upload a local directory to the persistent /data directory
remote_dir = sync_dir("path/to/local/dir", "/data/remote_dir")
# An isolated function to list the contents of the uploaded directory
@isolated()
def test():
import os
os.system(f"ls {remote_dir}")
# Execute the test function
test() # prints contents of the uploaded directory
In this example, the local directory specified by path/to/local/dir is uploaded to /data/sync/remote_dir in the fal-serverless environment. The isolated function test then lists the contents of the uploaded directory.
Notes
- The
sync_dir
function uses isolated functions to efficiently upload the directory contents in the background. - Uploaded files and directories are persistent in the
/data
directory on the fal-serverless platform. This allows you to access them across different isolated functions and invocations. - The
sync_dir
function should be called before the execution of any isolated functions that rely on the uploaded data.