Skip to content

Commit 52c42ce

Browse files
conflict
2 parents f040d5d + 920acc5 commit 52c42ce

25 files changed

+873
-131
lines changed

backend/controller/conversation_api.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -992,12 +992,12 @@ async def clear_download_progress(request):
992992
"message": f"Download ID {download_id} not found"
993993
})
994994

995-
@server.PromptServer.instance.routes.get("/api/model-suggests")
995+
@server.PromptServer.instance.routes.get("/api/model-searchs")
996996
async def model_suggests(request):
997997
"""
998-
Get model suggest list by keyword
998+
Get model search list by keyword
999999
"""
1000-
log.info("Received model-suggests request")
1000+
log.info("Received model-search request")
10011001
try:
10021002
keyword = request.query.get('keyword')
10031003

@@ -1010,17 +1010,17 @@ async def model_suggests(request):
10101010
# 创建ModelScope网关实例
10111011
gateway = ModelScopeGateway()
10121012

1013-
suggests = gateway.suggest(name=keyword)
1013+
suggests = gateway.search(name=keyword)
10141014

10151015
list = suggests["data"] if suggests.get("data") else []
10161016

10171017
return web.json_response({
10181018
"success": True,
10191019
"data": {
1020-
"suggests": list,
1020+
"searchs": list,
10211021
"total": len(list)
10221022
},
1023-
"message": f"Get suggests successfully"
1023+
"message": f"Get searchs successfully"
10241024
})
10251025

10261026
except ImportError as e:
@@ -1031,12 +1031,12 @@ async def model_suggests(request):
10311031
})
10321032

10331033
except Exception as e:
1034-
log.error(f"Error get model suggests: {str(e)}")
1034+
log.error(f"Error get model searchs: {str(e)}")
10351035
import traceback
10361036
traceback.print_exc()
10371037
return web.json_response({
10381038
"success": False,
1039-
"message": f"Get model suggests failed: {str(e)}"
1039+
"message": f"Get model searchs failed: {str(e)}"
10401040
})
10411041

10421042
@server.PromptServer.instance.routes.get("/api/model-paths")

backend/utils/modelscope_gateway.py

Lines changed: 142 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
class ModelScopeGateway:
2020
BASE_URL = "https://www.modelscope.cn"
2121
SUGGEST_ENDPOINT = f"{BASE_URL}/api/v1/dolphin/model/suggestv2"
22-
22+
SEARCH_ENDPOINT = f"{BASE_URL}/api/v1/dolphin/models"
23+
SEARCH_SINGLE_ENDPOINT = f"{BASE_URL}/api/v1/models"
24+
2325
def __init__(self, timeout: float = 10.0, retries: int = 3, backoff: float = 0.5):
2426
self.timeout = timeout
2527

@@ -36,13 +38,75 @@ def __init__(self, timeout: float = 10.0, retries: int = 3, backoff: float = 0.5
3638
total=retries,
3739
backoff_factor=backoff,
3840
status_forcelist=[429, 500, 502, 503, 504],
39-
allowed_methods=["GET", "POST"],
41+
allowed_methods=["GET", "POST", "PUT"],
4042
raise_on_status=False,
4143
)
4244
adapter = HTTPAdapter(max_retries=retry_cfg)
4345
self.session.mount("https://", adapter)
4446
self.session.mount("http://", adapter)
4547

48+
def formatData(self, data: Any) -> Dict[str, Any]:
49+
inner = data.get('Model', {}) if isinstance(data, dict) else {}
50+
path = data.get('Path') or inner.get('Path')
51+
name = data.get('Name') or inner.get('Name')
52+
revision = data.get('Revision') or inner.get('Revision')
53+
# size = self.get_model_size(path, name, revision)
54+
return {
55+
"Libraries": data.get("Libraries") or inner.get("Libraries"),
56+
"ChineseName": data.get("ChineseName") or inner.get("ChineseName"),
57+
"Id": data.get("Id") or inner.get("Id") or data.get("ModelId") or inner.get("ModelId"),
58+
"Name": data.get("Name") or inner.get("Name"),
59+
"Path": data.get("Path") or inner.get("Path"),
60+
"LastUpdatedTime": data.get("LastUpdatedTime") or inner.get("LastUpdatedTime") or data.get("LastUpdatedAt") or inner.get("LastUpdatedAt"),
61+
"Downloads": data.get("Downloads") or inner.get("Downloads") or data.get("DownloadCount") or inner.get("DownloadCount"),
62+
# "Size": size or 0
63+
}
64+
65+
def get_single_model(self, path: str, name: str) -> Optional[Dict[str, Any]]:
66+
"""
67+
调用单模型详情接口。
68+
返回原始 JSON(尽量保持结构,便于 formatData 处理),失败返回 None。
69+
"""
70+
if path is None or name is None:
71+
return None
72+
try:
73+
url = f"{self.SEARCH_SINGLE_ENDPOINT}/{path}/{name}"
74+
resp = self.session.get(url, timeout=self.timeout)
75+
resp.raise_for_status()
76+
body = resp.json()
77+
# 兼容不同返回包裹层级
78+
if isinstance(body, dict):
79+
data = body.get("Data") or body.get("data") or body
80+
return data
81+
return body
82+
except Exception as e:
83+
log.error(f"ModelScope single fetch failed for path={path}: name={name}: {e}")
84+
return None
85+
86+
def get_model_size(self, path: str, name: str, revision: str, root: str = '') -> int:
87+
"""
88+
调用单模型详情接口。
89+
返回原始 JSON(尽量保持结构,便于 formatData 处理),失败返回 None。
90+
"""
91+
if path is None or name is None or revision is None:
92+
return 0
93+
try:
94+
url = f"{self.SEARCH_SINGLE_ENDPOINT}/{path}/{name}/repo/files?Revision={revision}&Root={root}"
95+
resp = self.session.get(url, timeout=self.timeout)
96+
resp.raise_for_status()
97+
body = resp.json()
98+
# 兼容不同返回包裹层级
99+
if isinstance(body, dict):
100+
data = body["Data"]["Files"]
101+
size = 0
102+
for item in data:
103+
size += item.get("Size") or 0
104+
return size
105+
return 0
106+
except Exception as e:
107+
log.error(f"ModelScope model size fetch failed for path={path}: name={name}: rversion={rversion}: {e}")
108+
return 0
109+
46110
def suggest(
47111
self,
48112
name: str,
@@ -63,7 +127,11 @@ def suggest(
63127
"ChineseName": "中文名称",
64128
"Id": 294066,
65129
"Name": "SD3-Controlnet-Pose",
66-
"Path": "InstantX"
130+
"Path": "InstantX",
131+
"Libraries": ["pytorch","lora","safetensors"],
132+
"LastUpdatedTime": "1733042611",
133+
"Downloads": 100,
134+
"Size": 100000
67135
}
68136
]
69137
}
@@ -88,7 +156,77 @@ def suggest(
88156
or body['Data']['Model']['Suggests'] is None or (len(body['Data']['Model']['Suggests']) == 0):
89157
log.error(f"ModelScope suggest failed: {body}, request: {payload}")
90158
return {"data": None}
91-
return {"data": body['Data']['Model']['Suggests']}
159+
models = body['Data']['Model']['Suggests']
160+
picked: List[Dict[str, Any]] = []
161+
for item in models:
162+
base = item or {}
163+
inner = base.get('Model', {}) if isinstance(base, dict) else {}
164+
path = base.get('Path') or inner.get('Path')
165+
name = base.get('Name') or inner.get('Name')
166+
detail= self.get_single_model(path, name)
167+
data = self.formatData(detail or base)
168+
picked.append(data)
169+
total = body['Data']['Model'].get('TotalCount') or body['Data']['Model'].get('Total') or 0
170+
return {"data": picked, "total": total}
171+
172+
def search(
173+
self,
174+
name: str,
175+
page: int = 1,
176+
page_size: int = 30,
177+
sort_by: str = "Default",
178+
target: str = "",
179+
single_criterion: Optional[List[Dict[str, Any]]] = None,
180+
criterion: Optional[List[Dict[str, Any]]] = None,
181+
) -> Dict[str, Any]:
182+
"""
183+
调用 models 模糊搜索接口;返回 body 与当前 Cookie。
184+
185+
Returns:
186+
Dict[str, Any]: 返回的模型列表,格式为:
187+
{
188+
"data": [
189+
{
190+
"ChineseName": "中文名称",
191+
"Id": 294066,
192+
"Name": "SD3-Controlnet-Pose",
193+
"Path": "InstantX",
194+
"Libraries": ["pytorch","lora","safetensors"],
195+
"LastUpdatedTime": "1733042611",
196+
"Downloads": 100,
197+
"Size": 100000
198+
}
199+
]
200+
}
201+
"""
202+
payload = {
203+
"PageSize": page_size,
204+
"PageNumber": page,
205+
"SortBy": sort_by,
206+
"Target": target,
207+
"SingleCriterion": single_criterion or [],
208+
"Name": name,
209+
"Criterion" : criterion
210+
}
211+
212+
resp = self.session.put(
213+
self.SEARCH_ENDPOINT,
214+
json=payload,
215+
timeout=self.timeout,
216+
)
217+
resp.raise_for_status()
218+
body = resp.json()
219+
if body['Data'] is None or body['Data']['Model'] is None \
220+
or body['Data']['Model']['Models'] is None or (len(body['Data']['Model']['Models']) == 0):
221+
log.error(f"ModelScope search failed: {body}, request: {payload}")
222+
return {"data": None}
223+
models = body['Data']['Model']['Models'] or []
224+
picked: List[Dict[str, Any]] = []
225+
for item in models:
226+
data = self.formatData(item or {})
227+
picked.append(data)
228+
total = body['Data']['Model'].get('TotalCount') or body['Data']['Model'].get('Total') or 0
229+
return {"data": picked, "total": total}
92230

93231
def download_with_sdk(
94232
self,
Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)