Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

poc of use js front end to get loras list #156

Merged
merged 3 commits into from
Sep 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions js/share_lora_loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { api } from "../../../scripts/api.js";
import { app } from "../../scripts/app.js";
app.registerExtension({
name: "bizyair.siliconcloud.share.lora.loader",
async beforeRegisterNodeDef(nodeType, nodeData, app) {
if (nodeData.name === "BizyAir_SharedLoraLoader") {
async function onTextChange(share_id, canvas, comfynode) {
console.log("share_id:", share_id);
const response = await api.fetchApi(`/bizyair/modelhost/${share_id}/models/files?type=bizyair/lora`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});

const { data: loras_list } = await response.json();
// console.log("loras_list:", loras_list);
const lora_name_widget = comfynode.widgets.find(widget => widget.name === "lora_name");
if (loras_list.length > 0) {
lora_name_widget.value = loras_list[0];
lora_name_widget.options.values = loras_list;
} else {
console.log("No loras found in the response");
lora_name_widget.value = "";
lora_name_widget.options.values = [];
}
}

function setWigetCallback(){
const shareid_widget = this.widgets.find(widget => widget.name === "share_id");
if (shareid_widget) {
shareid_widget.callback = onTextChange;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

前端的主要作用,是通过设置 shareid 那个文本框的回调,监控文本改变事件。

然后在文本改变的事件里,像后端发请求,得到 loras list

} else {
console.log("share_id widget not found");
}
}
const onNodeCreated = nodeType.prototype.onNodeCreated
nodeType.prototype.onNodeCreated = function () {
onNodeCreated?.apply(this, arguments);
setWigetCallback.call(this, arguments);
};
}
},
})
2 changes: 1 addition & 1 deletion nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,7 @@ def INPUT_TYPES(s):
return {
"required": {
"share_id": ("STRING", {"default": "share_id"}),
"lora_name": ("STRING", {"default": "lora_name"}),
"lora_name": (folder_paths.get_filename_list("loras"),),
"model": (data_types.MODEL,),
"clip": (data_types.CLIP,),
"strength_model": (
Expand Down
53 changes: 24 additions & 29 deletions src/bizy_server/modelhost.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ async def list_model_files(request):
@prompt_server.routes.get(f"/{API_PREFIX}" + "/{shareId}/models/files")
async def list_share_model_files(request):
shareId = request.match_info["shareId"]

if not self.is_string_valid(shareId):
return ErrResponse(INVALID_SHARE_ID)

Expand Down Expand Up @@ -528,41 +529,35 @@ async def get_model_files(self, payload) -> (dict, ErrorNo):
return result, None

async def get_share_model_files(self, shareId, payload) -> (dict, ErrorNo):
headers, err = self.auth_header()
if err is not None:
return None, err

server_url = f"{BIZYAIR_SERVER_ADDRESS}/{shareId}/models/files"
try:
resp = self.do_get(server_url, params=payload, headers=headers)
ret = json.loads(resp)
if ret["code"] != CODE_OK:
if ret["code"] == CODE_NO_MODEL_FOUND:
return [], None
else:
return None, ErrorNo(500, ret["code"], None, ret["message"])

if not ret["data"]:
return [], None
except Exception as e:
print(f"fail to list share model files: {str(e)}")
return None, LIST_SHARE_MODEL_FILE_ERR
def callback(ret: dict):
if ret["code"] != CODE_OK:
if ret["code"] == CODE_NO_MODEL_FOUND:
return [], None
else:
return [], ErrorNo(500, ret["code"], None, ret["message"])

files = ret["data"]["files"]
result = []
if len(files) > 0:
tree = defaultdict(lambda: {"name": "", "list": []})
if not ret or "data" not in ret or ret["data"] is None:
return [], None

for item in files:
parts = item["label_path"].split("/")
model_name = parts[0]
if model_name not in tree:
tree[model_name] = {"name": model_name, "list": [item]}
else:
tree[model_name]["list"].append(item)
result = list(tree.values())
outputs = [
x["label_path"] for x in ret["data"]["files"] if x["label_path"]
]
outputs = bizyair.path_utils.filter_files_extensions(
outputs,
extensions=bizyair.path_utils.path_manager.supported_pt_extensions,
)
return outputs, None

return result, None
ret = await bizyair.common.client.async_send_request(
method="GET", url=server_url, params=payload, callback=callback
)
return ret[0], ret[1]
except Exception as e:
print(f"fail to list share model files: {str(e)}")
return [], LIST_SHARE_MODEL_FILE_ERR

async def get_models(self, payload) -> (dict, ErrorNo):
headers, err = self.auth_header()
Expand Down
45 changes: 45 additions & 0 deletions src/bizyair/common/client.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import asyncio
import json
import pprint
import urllib.error
import urllib.request
import warnings

import aiohttp

__all__ = ["send_request"]

from dataclasses import dataclass, field
Expand Down Expand Up @@ -134,6 +137,48 @@ def send_request(
return json.loads(response_data)


async def async_send_request(
method: str = "POST",
url: str = None,
data: bytes = None,
verbose=False,
callback: callable = process_response_data,
**kwargs,
) -> dict:
headers = kwargs.pop("headers") if "headers" in kwargs else _headers()
try:
async with aiohttp.ClientSession() as session:
async with session.request(
method, url, data=data, headers=headers, **kwargs
) as response:
response_data = await response.text()
if response.status != 200:
error_message = f"HTTP Status {response.status}"
if verbose:
print(f"Error encountered: {error_message}")
if response.status == 401:
raise PermissionError(
"Key is invalid, please refer to https://cloud.siliconflow.cn to get the API key.\n"
"If you have the key, please click the 'BizyAir Key' button at the bottom right to set the key."
)
else:
raise ConnectionError(
f"Failed to connect to the server: {error_message}.\n"
+ "Please check your API key and ensure the server is reachable.\n"
+ "Also, verify your network settings and disable any proxies if necessary.\n"
+ "After checking, please restart the ComfyUI service."
)
if callback:
return callback(json.loads(response_data))
return json.loads(response_data)
except aiohttp.ClientError as e:
print(f"Error fetching data: {e}")
return {}
except Exception as e:
print(f"Error fetching data: {str(e)}")
return {}


def fetch_models_by_type(
url: str, model_type: str, *, method="GET", verbose=False
) -> dict:
Expand Down
1 change: 1 addition & 0 deletions src/bizyair/path_utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
guess_config,
guess_url_from_node,
)
from .utils import filter_files_extensions
Loading