Skip to content

Commit

Permalink
Merge branch 'main' of github.com:amun-ai/hypha
Browse files Browse the repository at this point in the history
  • Loading branch information
oeway committed Nov 26, 2024
2 parents 6390353 + efb038b commit 89e4fb2
Show file tree
Hide file tree
Showing 15 changed files with 89 additions and 96 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Hypha Change Log

### 0.20.40

- Add vector store service to support vector search and retrieval.
- Fix zenodo file upload issue
- Speed up server by removing the `asyncio.sleep(0.01)` throttling and support concurrent handling of events in the redis event bus.

### 0.20.39

- Revise artifact manager to use artifact id as the primary key, remove `prefix` based keys.
Expand Down
2 changes: 1 addition & 1 deletion docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ svc = await get_remote_service("http://localhost:9527/ws-user-scintillating-lawy
Include the following script in your HTML file to load the `hypha-rpc` client:

```html
<script src="https://cdn.jsdelivr.net/npm/[email protected].39/dist/hypha-rpc-websocket.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected].40/dist/hypha-rpc-websocket.min.js"></script>
```

Use the following code in JavaScript to connect to the server and access an existing service:
Expand Down
10 changes: 5 additions & 5 deletions docs/migration-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ To connect to the server, instead of installing the `imjoy-rpc` module, you will
pip install -U hypha-rpc # new install
```

We also changed our versioning strategy, we use the same version number for the server and client, so it's easier to match the client and server versions. For example, `hypha-rpc` version `0.20.39` is compatible with Hypha server version `0.20.39`.
We also changed our versioning strategy, we use the same version number for the server and client, so it's easier to match the client and server versions. For example, `hypha-rpc` version `0.20.40` is compatible with Hypha server version `0.20.40`.

#### 2. Change the imports to use `hypha-rpc`

Expand Down Expand Up @@ -128,10 +128,10 @@ loop.run_forever()
To connect to the server, instead of using the `imjoy-rpc` module, you will need to use the `hypha-rpc` module. The `hypha-rpc` module is a standalone module that provides the RPC connection to the Hypha server. You can include it in your HTML using a script tag:

```html
<script src="https://cdn.jsdelivr.net/npm/[email protected].39/dist/hypha-rpc-websocket.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected].40/dist/hypha-rpc-websocket.min.js"></script>
```

We also changed our versioning strategy, we use the same version number for the server and client, so it's easier to match the client and server versions. For example, `hypha-rpc` version `0.20.39` is compatible with Hypha server version `0.20.39`.
We also changed our versioning strategy, we use the same version number for the server and client, so it's easier to match the client and server versions. For example, `hypha-rpc` version `0.20.40` is compatible with Hypha server version `0.20.40`.

#### 2. Change the connection method and use camelCase for service function names

Expand All @@ -149,7 +149,7 @@ Here is a suggested list of search and replace operations to update your code:
Here is an example of how the updated code might look:

```html
<script src="https://cdn.jsdelivr.net/npm/[email protected].39/dist/hypha-rpc-websocket.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected].40/dist/hypha-rpc-websocket.min.js"></script>
<script>
async function main(){
const server = await hyphaWebsocketClient.connectToServer({"server_url": "https://hypha.amun.ai"});
Expand Down Expand Up @@ -197,7 +197,7 @@ We created a tutorial to introduce this new feature: [service type annotation](.
Here is a quick example in JavaScript:

```html
<script src="https://cdn.jsdelivr.net/npm/[email protected].39/dist/hypha-rpc-websocket.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected].40/dist/hypha-rpc-websocket.min.js"></script>

<script>
async function main(){
Expand Down
2 changes: 1 addition & 1 deletion docs/service-type-annotation.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ if __name__ == "__main__":
**JavaScript Client: Service Usage**

```html
<script src="https://cdn.jsdelivr.net/npm/[email protected].39/dist/hypha-rpc-websocket.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected].40/dist/hypha-rpc-websocket.min.js"></script>
<script>
async function main() {
const server = await hyphaWebsocketClient.connectToServer({"server_url": "https://hypha.amun.ai"});
Expand Down
2 changes: 1 addition & 1 deletion helm-charts/aks-hypha.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ replicaCount: 1
image:
repository: ghcr.io/amun-ai/hypha
pullPolicy: IfNotPresent
tag: "0.20.39"
tag: "0.20.40"
serviceAccount:
create: true
Expand Down
2 changes: 1 addition & 1 deletion helm-charts/hypha-server/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.20.39
version: 0.20.40

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
Expand Down
2 changes: 1 addition & 1 deletion helm-charts/hypha-server/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ image:
repository: ghcr.io/amun-ai/hypha
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: "0.20.39"
tag: "0.20.40"

imagePullSecrets: []
nameOverride: ""
Expand Down
115 changes: 49 additions & 66 deletions hypha/artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,8 +313,7 @@ async def create_zip_file(
# List all files in the artifact
root_dir_key = safe_join(
s3_config["prefix"],
workspace,
f"{self._artifacts_dir}/{artifact.id}/v{version_index}",
f"{artifact.id}/v{version_index}",
)

async def list_all_files(dir_path=""):
Expand Down Expand Up @@ -392,8 +391,7 @@ async def member_files():
async for path in files:
file_key = safe_join(
s3_config["prefix"],
workspace,
f"{self._artifacts_dir}/{artifact.id}/v{version_index}",
f"{artifact.id}/v{version_index}",
path,
)
logger.info(f"Adding file to ZIP: {file_key}")
Expand Down Expand Up @@ -516,8 +514,7 @@ async def get_zip_file_content(
# Full key of the ZIP file in the S3 bucket
s3_key = safe_join(
s3_config["prefix"],
workspace,
f"{self._artifacts_dir}/{artifact.id}/v{version_index}/{zip_file_path}",
f"{artifact.id}/v{version_index}/{zip_file_path}",
)

# Fetch the ZIP file metadata from S3 (to avoid downloading the whole file)
Expand Down Expand Up @@ -723,8 +720,7 @@ async def get_file(
s3_config = self._get_s3_config(artifact, parent_artifact)
file_key = safe_join(
s3_config["prefix"],
workspace,
f"{self._artifacts_dir}/{artifact.id}/v{version_index}",
f"{artifact.id}/v{version_index}",
path,
)
if path.endswith("/") or path == "":
Expand Down Expand Up @@ -1132,7 +1128,7 @@ def _get_s3_config(self, artifact, parent_artifact):
"secret_access_key": self.s3_controller.secret_access_key,
"region_name": self.s3_controller.region_name,
"bucket": self.workspace_bucket,
"prefix": "",
"prefix": safe_join(artifact.workspace, self._artifacts_dir),
"public_endpoint_url": None,
}
if self.s3_controller.enable_s3_proxy:
Expand Down Expand Up @@ -1269,8 +1265,6 @@ async def _save_version_to_s3(self, version_index: int, artifact, s3_config):
async with self._create_client_async(s3_config) as s3_client:
version_key = safe_join(
s3_config["prefix"],
artifact.workspace,
f"{self._artifacts_dir}",
artifact.id,
f"v{version_index}.json",
)
Expand All @@ -1295,8 +1289,6 @@ async def _load_version_from_s3(
s3_config = self._get_s3_config(artifact, parent_artifact)
version_key = safe_join(
s3_config["prefix"],
artifact.workspace,
f"{self._artifacts_dir}",
artifact.id,
f"v{version_index}.json",
)
Expand Down Expand Up @@ -1348,8 +1340,6 @@ async def _delete_version_files_from_s3(
async with self._create_client_async(s3_config) as s3_client:
version_key = safe_join(
s3_config["prefix"],
artifact.workspace,
f"{self._artifacts_dir}",
artifact.id,
f"v{version_index}",
)
Expand Down Expand Up @@ -1798,46 +1788,45 @@ async def commit(

versions = artifact.versions or []
artifact.config = artifact.config or {}
if artifact.staging:
s3_config = self._get_s3_config(artifact, parent_artifact)
async with self._create_client_async(
s3_config,
) as s3_client:
download_weights = {}
for file_info in artifact.staging:
file_key = safe_join(
s3_config["prefix"],
artifact.workspace,
f"{self._artifacts_dir}/{artifact.id}/v{version_index}/{file_info['path']}",
)
try:
await s3_client.head_object(
Bucket=s3_config["bucket"], Key=file_key
)
except ClientError:
raise FileNotFoundError(
f"File '{file_info['path']}' does not exist in the artifact."
)
if (
file_info.get("download_weight") is not None
and file_info["download_weight"] > 0
):
download_weights[file_info["path"]] = file_info[
"download_weight"
]
if download_weights:
artifact.config["download_weights"] = download_weights
flag_modified(artifact, "config")

artifact.file_count = await self._count_files_in_prefix(
s3_client,
s3_config["bucket"],
safe_join(
s3_config["prefix"],
artifact.workspace,
f"{self._artifacts_dir}/{artifact.id}/v{version_index}",
),

s3_config = self._get_s3_config(artifact, parent_artifact)
async with self._create_client_async(
s3_config,
) as s3_client:
download_weights = {}
for file_info in artifact.staging or []:
file_key = safe_join(
s3_config["prefix"],
f"{artifact.id}/v{version_index}/{file_info['path']}",
)
try:
await s3_client.head_object(
Bucket=s3_config["bucket"], Key=file_key
)
except ClientError:
raise FileNotFoundError(
f"File '{file_info['path']}' does not exist in the artifact."
)
if (
file_info.get("download_weight") is not None
and file_info["download_weight"] > 0
):
download_weights[file_info["path"]] = file_info[
"download_weight"
]

if download_weights:
artifact.config["download_weights"] = download_weights
flag_modified(artifact, "config")

artifact.file_count = await self._count_files_in_prefix(
s3_client,
s3_config["bucket"],
safe_join(
s3_config["prefix"],
f"{artifact.id}/v{version_index}",
),
)

parent_artifact_config = (
parent_artifact.config if parent_artifact else {}
Expand Down Expand Up @@ -1925,8 +1914,7 @@ async def delete(
if delete_files:
artifact_path = safe_join(
s3_config["prefix"],
artifact.workspace,
f"{self._artifacts_dir}/{artifact.id}",
artifact.id,
)
async with self._create_client_async(
s3_config,
Expand Down Expand Up @@ -2172,8 +2160,7 @@ async def put_file(
) as s3_client:
file_key = safe_join(
s3_config["prefix"],
artifact.workspace,
f"{self._artifacts_dir}/{artifact.id}/v{version_index}/{file_path}",
f"{artifact.id}/v{version_index}/{file_path}",
)
presigned_url = await s3_client.generate_presigned_url(
"put_object",
Expand Down Expand Up @@ -2236,8 +2223,7 @@ async def remove_file(self, artifact_id, file_path, context: dict):
) as s3_client:
file_key = safe_join(
s3_config["prefix"],
artifact.workspace,
f"{self._artifacts_dir}/{artifact.id}/v{version_index}/{file_path}",
f"{artifact.id}/v{version_index}/{file_path}",
)
await s3_client.delete_object(
Bucket=s3_config["bucket"], Key=file_key
Expand Down Expand Up @@ -2272,8 +2258,7 @@ async def get_file(
) as s3_client:
file_key = safe_join(
s3_config["prefix"],
artifact.workspace,
f"{self._artifacts_dir}/{artifact.id}/v{version_index}/{file_path}",
f"{artifact.id}/v{version_index}/{file_path}",
)
try:
await s3_client.head_object(
Expand Down Expand Up @@ -2342,17 +2327,15 @@ async def list_files(
full_path = (
safe_join(
s3_config["prefix"],
artifact.workspace,
f"{self._artifacts_dir}/{artifact.id}/v{version_index}/{dir_path}",
f"{artifact.id}/v{version_index}/{dir_path}",
)
+ "/"
)
else:
full_path = (
safe_join(
s3_config["prefix"],
artifact.workspace,
f"{self._artifacts_dir}/{artifact.id}/v{version_index}",
f"{artifact.id}/v{version_index}",
)
+ "/"
)
Expand Down
2 changes: 1 addition & 1 deletion hypha/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ async def process_message(msg):
self._ready.set_result(True)
while not self._stop:
msg = await pubsub.get_message(
ignore_subscribe_messages=True, timeout=0.1
ignore_subscribe_messages=True, timeout=0.05
)
if msg:
asyncio.create_task(process_message(msg)) # Add task to pool
Expand Down
13 changes: 7 additions & 6 deletions hypha/core/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -907,10 +907,11 @@ async def teardown(self):
await self.remove_client(
client_id, self._root_user.get_workspace(), self._root_user, unload=True
)
websockets = self._websocket_server.get_websockets()
for ws in websockets.values():
try:
await ws.close()
except GeneratorExit:
pass
if self._websocket_server:
websockets = self._websocket_server.get_websockets()
for ws in websockets.values():
try:
await ws.close()
except GeneratorExit:
pass
logger.info("Teardown complete")
2 changes: 1 addition & 1 deletion hypha/templates/hypha-core-app/hypha-app-webpython.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ loadPyodide().then(async (pyodide) => {
pyodide.setStderr({ batched: (msg) => console.error(msg) });
await pyodide.loadPackage("micropip");
const micropip = pyodide.pyimport("micropip");
await micropip.install('hypha-rpc==0.20.39');
await micropip.install('hypha-rpc==0.20.40');
const isWindow = typeof window !== "undefined";

setTimeout(() => {
Expand Down
4 changes: 2 additions & 2 deletions hypha/templates/ws/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@
<body class="bg-black text-white font-poppins">
<div id="app"></div>
<script type="module">
import { HyphaCore } from "https://cdn.jsdelivr.net/npm/[email protected].39/dist/hypha-core.mjs";
import { HyphaCore } from "https://cdn.jsdelivr.net/npm/[email protected].40/dist/hypha-core.mjs";

const defaultService = {
getServerConfig(context){
Expand Down Expand Up @@ -765,7 +765,7 @@ <h2 className="text-2xl font-bold text-white">Artifact Details</h2>
<h3 className="text-lg font-bold">Files:</h3>
<ul className="list-disc list-inside text-gray-300 mt-2">
{files.map((file) => (
<li key={file.name} className="break-all flex items-center justify-between">
<li key={file.name} className="break-all flex mb-1 items-center justify-between">
<span><i className={`fas ${file.type==='directory' ? 'fa-folder' : 'fa-file-alt'} mr-2`}></i>{file.name}</span>
{file.type === "file" && (
<div className="flex space-x-2">
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ aiofiles==23.2.1
websockets==13.1
base58==2.1.1
fastapi==0.106.0
hypha-rpc==0.20.39
hypha-rpc==0.20.40
jinja2==3.1.4
lxml==4.9.3
msgpack==1.0.8
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
REQUIREMENTS = [
"aiofiles",
"fastapi>=0.70.0,<=0.106.0",
"hypha-rpc>=0.20.39",
"hypha-rpc>=0.20.40",
"msgpack>=1.0.2",
"numpy",
"pydantic[email]>=2.6.1",
Expand Down
Loading

0 comments on commit 89e4fb2

Please sign in to comment.