Function은 Modal에서 실행가능한 최소 단위입니다. 하나의 App 안에 여러 개의 Function이 존재할 수 있지만, 이들은 모두 독립적으로 실행하거나 확장할 수 있습니다. 덕분에 서버에서 특정 Function을 호출하지 않으면 그 Function은 컨테이너에도 올라가지 않아 자원을 효율적으로 사용할 수 있습니다.
일반적으로 Function 클래스를 직접 사용하여 생성하지 않고, @app.function( ) 데코레이션을 통해 생성합니다.
@app.function()
def f():
print("Hello world!")
@app.function()
def g():
print("Goodbye world!")
이런 식으로 정의된 함수는 App에 속하게 되고, 나중에 remote( )로 실행할수 있게 됩니다.
Entrypoint
Entrypoint는 ephemeral App에서 modal run명령어를 실행했을 때 가장 먼저 실행되는 코드를 의미합니다.
@app.local_entrypoint( ) 데코레이션을 통해 선언할 수 있습니다. 만약 App에 하나의 Function 만이 존재한다면, 데코레이션이 없어도 그 함수가 자동으로 entrypoint가 됩니다.
@app.local_entrypoint()
def main():
f.remote()
Argument parsing
Entrypoint 함수에 기본타입(int, str 등)의 매개변수를 사용하면, modal cli에서 자동으로 매개변수를 사용할 수 있도록 파싱해줍니다.
# script.py
@app.local_entrypoint()
def main(foo: int, bar: str):
some_modal_function.remote(foo, bar)
가령 위와 같이 int 타입의 foo와 str 타입의 bar를 매개변수를 사용했으면, 프롬프트에서 다음과 같이 사용할 수 있게 됩니다.
modal run script.py --foo 1 --bar "hello"
Entrypoint 직접 설정
기본적으로 modal run script.py는 local_entrypoint를 실행하지만, modal run script.py::app.f와 같이 직접 실행하고자 하는 함수를 지정할 수도 있습니다.
# script.py
@app.function()
def f():
print("Hello world!")
@app.function()
def g():
print("Goodbye world!")
@app.local_entrypoint()
def main():
f.remote()
메소드
| 메소드 | 기능 | 반환값 |
| hydrate( ) | 로컬 환경의 객체와 Modal 서버의 객체를 동기화 | None |
| update_autoscaler( ) | autoscaler 오버라이딩 | None |
| from_name( ) | 해당 이름의 deployed App Function을 참조 | _Function |
| get_web_uri( ) * | web endpoint로 실행할 때 접근할 수 있는 url 반환 | str |
| remote( ) * | Funtion 원격 실행 (Modal에서) | ReturnType |
| remote_gen( ) | Generator 원격 실행 (Modal에서) | AsyncGenerator |
| local( ) | Function 로컬에서 실행 | OriginalReturnType |
| spawn( ) | Function 실행 후 기다림 없이 즉시 반환 | _FunctionCall |
| get_raw_f( ) | 이 Function으로 감싸진 Python 객체(함수)를 반환 | Callable |
| get_current_stats( ) | 이 Function의 queue나 runner count 등의 상태를 반환 | FunctionStats |
| map( ) | map 함수 | AsyncOrSyncIterable |
| starmap( ) | 둘 이상의 매개변수에 대한 map 함수 | AsyncOrSyncIterable |
| for_each( ) | for 구문 함수 | |
| spawn_map( ) | 동시 실행하는 map 함수 | None |
hydrate( )
def hydrate(self, client: Optional[_Client] = None) -> Self:
update_autoscaler( )
@live_method
def update_autoscaler(
self,
*,
min_containers: Optional[int] = None,
max_containers: Optional[int] = None,
buffer_containers: Optional[int] = None,
scaledown_window: Optional[int] = None,
) -> None:
from_name( )
@classmethod
def from_name(
cls: type["_Function"],
app_name: str,
name: str,
*,
environment_name: Optional[str] = None,
client: Optional[_Client] = None,
) -> "_Function":
get_web_url( )
@live_method
def get_web_url(self) -> Optional[str]:
remote( )
@live_method
def remote(self, *args: P.args, **kwargs: P.kwargs) -> ReturnType:
remote_gen( )
@live_method_gen
def remote_gen(self, *args, **kwargs) -> AsyncGenerator[Any, None]:
local( )
def local(self, *args: P.args, **kwargs: P.kwargs) -> OriginalReturnType:
spawn( )
@live_method
def spawn(self, *args: P.args, **kwargs: P.kwargs) -> "_FunctionCall[ReturnType]":
get_raw_f( )
def get_raw_f(self) -> Callable[..., Any]:
get_current_stats( )
@live_method
def get_current_stats(self) -> FunctionStats:
map( )
@warn_if_generator_is_not_consumed(function_name="Function.map")
def map(
self,
*input_iterators: typing.Iterable[Any], # one input iterator per argument in the mapped-over function/generator
kwargs={}, # any extra keyword arguments for the function
order_outputs: bool = True, # return outputs in order
return_exceptions: bool = False, # propagate exceptions (False) or aggregate them in the results list (True)
wrap_returned_exceptions: bool = True,
) -> AsyncOrSyncIterable:
해당 Function을 이용해 입력값에 대해 map 연산을 수행합니다. 다수의 입력값이 들어올 경우 입력된 순서와 동일하게 출력값을 반환합니다. order_outputs=False 일 때는 먼저 연산이 종료된 순서로 반환합니다.
@app.function()
def my_func(a):
return a ** 2
@app.local_entrypoint()
def main():
assert list(my_func.map([1, 2, 3, 4])) == [1, 4, 9, 16]
starmap( )
@warn_if_generator_is_not_consumed(function_name="Function.starmap")
def starmap(
self,
input_iterator: typing.Iterable[typing.Sequence[Any]],
*,
kwargs={},
order_outputs: bool = True,
return_exceptions: bool = False,
wrap_returned_exceptions: bool = True,
) -> AsyncOrSyncIterable:
map( )과 동일하지만, Function의 매개변수가 둘 이상일 때 사용합니다.
@app.function()
def my_func(a, b):
return a + b
@app.local_entrypoint()
def main():
assert list(my_func.starmap([(1, 2), (3, 4)])) == [3, 7]
for_each( )
def for_each(self, *input_iterators, kwargs={}, ignore_exceptions: bool = False):
일반적인 for 반복문과 같습니다. map( )과는 달리 반환값은 필요하지 않고 함수 호출만 필요한 경우일 때 사용할 수 있습니다.
spawn_map( )
def spawn_map(self, *input_iterators, kwargs={}) -> None:
입력값에 대해 동시 실행(parallel execution)이 가능합니다.
'ML' 카테고리의 다른 글
| [Modal] 03. Secret (0) | 2025.12.31 |
|---|---|
| [Modal] 01. App (1) | 2025.12.30 |
| [Modal] App, Function, Entrypoint (0) | 2025.12.29 |
| [Modal] Modal에 대하여 (0) | 2025.12.28 |
| [GAN] Style 적대적 생성 신경망 (StyleGAN) (0) | 2023.04.28 |