-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
use hypha-rpc and add ray app loader
- Loading branch information
Showing
31 changed files
with
159 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
include environments/* | ||
recursive-include bioimageio/apps | ||
recursive-include bioimageio/engine/apps * | ||
recursive-include bioimageio/engine/ray_apps * | ||
global-exclude *.pyc | ||
global-exclude *__pycache__* |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
"""Provide main entrypoint.""" | ||
import asyncio | ||
from ray import serve | ||
import logging | ||
import os | ||
import sys | ||
from pathlib import Path | ||
import urllib.request | ||
from starlette.requests import Request | ||
from starlette.responses import HTMLResponse | ||
|
||
from hypha_rpc.utils import ObjectProxy | ||
from hypha_rpc.sync import connect_to_server | ||
|
||
logging.basicConfig(stream=sys.stdout) | ||
logger = logging.getLogger("app_launcher") | ||
logger.setLevel(logging.INFO) | ||
|
||
|
||
def load_app(plugin_file): | ||
"""Load app file.""" | ||
if os.path.isfile(plugin_file): | ||
with open(plugin_file, "r", encoding="utf-8") as fil: | ||
content = fil.read() | ||
elif plugin_file.startswith("http"): | ||
with urllib.request.urlopen(plugin_file) as response: | ||
content = response.read().decode("utf-8") | ||
# remove query string | ||
plugin_file = plugin_file.split("?")[0] | ||
else: | ||
raise Exception(f"Invalid input app file path: {plugin_file}") | ||
|
||
if plugin_file.endswith(".py"): | ||
app_config = ObjectProxy() | ||
import hypha_rpc | ||
def export(app_class, config=None): | ||
app_config.update(config or {}) | ||
app_config.app_class = app_class | ||
hypha_rpc.api = ObjectProxy(export=export) | ||
exec(content, globals()) # pylint: disable=exec-used | ||
logger.info("Plugin executed") | ||
return app_config | ||
else: | ||
raise RuntimeError(f"Invalid script file type ({plugin_file})") | ||
|
||
@serve.deployment | ||
class HyphaApp: | ||
def __init__(self, server_url, workspace, token, services): | ||
self._services = services | ||
self._hypha_server = connect_to_server({"server_url": "https://hypha.aicell.io", "token": token, "workspace": workspace}) | ||
svc = { | ||
"name": "Ray Functions", | ||
"id": "ray-functions", | ||
"config": { | ||
"visibility": "protected" | ||
}, | ||
} | ||
|
||
def create_service_function(name, service_handle): | ||
async def service_function(*args, **kwargs): | ||
return await service_handle.translate.remote(*args, **kwargs) | ||
service_function.__name__ = name | ||
return service_function | ||
|
||
for service_name, service_bind in self._services.items(): | ||
svc[service_name] = create_service_function(service_name, service_bind) | ||
info = self._hypha_server.register_service(svc, {"overwrite":True}) | ||
print("Hypha service info:", info) | ||
self.info = info | ||
|
||
async def __call__(self, request: Request): | ||
redirect_url = f"https://hypha.aicell.io/{self.info.config.workspace}/services/{self.info.id.split('/')[1]}/translator?text=hello" | ||
return HTMLResponse( | ||
""" | ||
<html> | ||
<head> | ||
<meta http-equiv="refresh" content="2; URL='{}'" /> | ||
</head> | ||
<body> | ||
<p>Redirecting to Hypha...</p> | ||
<h1>Services:</h1> | ||
<ul> | ||
{} | ||
</ul> | ||
</body> | ||
</html> | ||
""".format(redirect_url, "\n".join([f"<li>{name}</li>" for name in self._services.keys()])) | ||
) | ||
|
||
|
||
current_dir = Path(os.path.dirname(os.path.realpath(__file__))) | ||
|
||
ray_apps = {} | ||
apps_dir = current_dir / "ray_apps" | ||
for app_file in apps_dir.iterdir(): | ||
if app_file.is_file() and app_file.suffix == ".py" and app_file.stem != "__init__": | ||
load_app(str(app_file)) | ||
app_info = load_app(str(app_file)) | ||
app_deployment = serve.deployment(name=app_info.name)(app_info.app_class).bind() | ||
ray_apps[app_info.name] = app_deployment | ||
|
||
# Getting config from environment | ||
server_url = os.environ.get("HYPHA_SERVER_URL") | ||
workspace = os.environ.get("HYPHA_WORKSPACE") | ||
token = os.environ.get("HYPHA_TOKEN") | ||
|
||
app = HyphaApp.bind(server_url, workspace, token, ray_apps) | ||
|
||
if __name__ == "__main__": | ||
serve.start() | ||
serve.run(app, name="hypha-apps") | ||
import asyncio | ||
asyncio.get_event_loop().run_forever() |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
from hypha_rpc import api | ||
from transformers import pipeline | ||
|
||
|
||
class Translator: | ||
def __init__(self): | ||
# Load model | ||
self.model = pipeline("translation_en_to_fr", model="t5-small") | ||
|
||
def translate(self, text: str) -> str: | ||
# Run inference | ||
model_output = self.model(text) | ||
|
||
# Post-process output to return only the translation text | ||
translation = model_output[0]["translation_text"] | ||
|
||
return translation | ||
|
||
|
||
api.export(Translator, {"name": "translator"}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
# BioEngine API | ||
|
||
Under the hood, BioEngine uses [Hypha](https://ha.amun.ai/) to orchestrate the services provided in the containers. We uses the `imjoy-rpc` client to communicate to the Hypha server for model execution. | ||
Under the hood, BioEngine uses [Hypha](https://ha.amun.ai/) to orchestrate the services provided in the containers. We uses the `hypha-rpc` client to communicate to the Hypha server for model execution. | ||
|
||
We provide a free public server for the BioEngine available at https://ai.imjoy.io. | ||
|
||
|
@@ -17,10 +17,10 @@ If you are interested in setting up your own BioEngine server, please check our | |
|
||
## Using BioEngine in Python | ||
|
||
First install the `imjoy-rpc` library: | ||
First install the `hypha-rpc` library: | ||
|
||
```bash | ||
pip install imjoy-rpc | ||
pip install hypha-rpc | ||
``` | ||
|
||
Use the following code to connect to the server and access the service. The code first connects to the server and then gets the service by its ID. The service can then be used like a normal Python object. | ||
|
@@ -98,18 +98,18 @@ if __name__ == "__main__": | |
|
||
> [!NOTE] | ||
> In Python, the recommended way to interact with the server to use asynchronous functions with `asyncio`. However, if you need to use synchronous functions, | ||
> you can use `from imjoy_rpc.hypha.sync import login, connect_to_server` (available since `imjoy-rpc>=0.5.25.post0`) instead. | ||
> They have the exact same arguments as the asynchronous versions. For more information, see [Synchronous Wrapper](https://github.com/imjoy-team/imjoy-rpc/blob/master/imjoy-rpc-v2.md#synchronous-wrapper) | ||
> you can use `from imjoy_rpc.hypha.sync import login, connect_to_server` (available since `hypha-rpc>=0.5.25.post0`) instead. | ||
> They have the exact same arguments as the asynchronous versions. For more information, see [Synchronous Wrapper](https://github.com/imjoy-team/hypha-rpc/blob/master/hypha-rpc-v2.md#synchronous-wrapper) | ||
> <strong>💡 Tip </strong><br> | ||
> For QT-based applications, e.g. napari, imswitch, use the synchronous api. | ||
## Using the BioEingine in JavaScript | ||
|
||
Include the following script in your HTML file to load the `imjoy-rpc` client: | ||
Include the following script in your HTML file to load the `hypha-rpc` client: | ||
|
||
```html | ||
<script src="https://cdn.jsdelivr.net/npm/imjoy[email protected]/dist/hypha-rpc-websocket.min.js"></script> | ||
<script src="https://cdn.jsdelivr.net/npm/hypha[email protected]/dist/hypha-rpc-websocket.min.js"></script> | ||
``` | ||
|
||
Use the following code in JavaScript to connect to the hypha server and access the bioenigne service via the `triton-client`: | ||
|
@@ -119,7 +119,7 @@ async function main(){ | |
const server = await hyphaWebsocketClient.connectToServer({"server_url": "https://ai.imjoy.io"}) | ||
const svc = await server.getService("triton-client") | ||
// encode the image, similar to np.random.randint(0, 255, (1, 3, 256, 256)) | ||
// see https://github.com/imjoy-team/imjoy-rpc/blob/master/imjoy-rpc-v2.md#data-type-representation | ||
// see https://github.com/imjoy-team/hypha-rpc/blob/master/hypha-rpc-v2.md#data-type-representation | ||
image = {_rtype: "ndarray", _rvalue: new ArrayBuffer(1*3*256*256), _rshape: [1, 3, 256, 256], _rdtype: "uint8"} | ||
ret = await triton.execute({ | ||
inputs: [{"inputs": [image], "model_id": "conscientious-seashell"}], | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,5 +8,5 @@ dependencies: | |
- openjdk=8 | ||
- pip | ||
- pip: | ||
- imjoy-rpc | ||
- hypha-rpc | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.