ap-client 0.6.0.dev1__tar.gz → 0.6.0.dev2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/PKG-INFO +1 -1
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/ap_client/api.py +38 -1
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/ap_client/cli.py +78 -4
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/ap_client/managed_ak.py +16 -5
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/pyproject.toml +1 -1
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/ap_client/__init__.py +0 -0
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/ap_client/akpool_commands.py +0 -0
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/ap_client/config.py +0 -0
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/ap_client/dataset_commands.py +0 -0
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/ap_client/dataset_register.py +0 -0
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/ap_client/exporter.py +0 -0
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/ap_client/fs_commands.py +0 -0
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/ap_client/instance_commands.py +0 -0
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/ap_client/irepo_sdk.py +0 -0
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/ap_client/manifest_view.py +0 -0
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/ap_client/profile_commands.py +0 -0
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/ap_client/repo_read_guard.py +0 -0
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/ap_client/share_api.py +0 -0
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/ap_client/split_publish.py +0 -0
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/ap_client/tbb.py +0 -0
- {ap_client-0.6.0.dev1 → ap_client-0.6.0.dev2}/ap_client/waiter.py +0 -0
|
@@ -1125,8 +1125,15 @@ class APIClient:
|
|
|
1125
1125
|
benchmark: Optional[str] = None,
|
|
1126
1126
|
experiment: Optional[str] = None,
|
|
1127
1127
|
ak_ids: Optional[list[str]] = None,
|
|
1128
|
+
priority: Optional[str] = None,
|
|
1129
|
+
priority_weight: Optional[int] = None,
|
|
1128
1130
|
) -> dict:
|
|
1129
|
-
"""Create a group.
|
|
1131
|
+
"""Create a group with optional scheduling defaults for its Jobs.
|
|
1132
|
+
|
|
1133
|
+
Omitted priority fields use the server defaults: medium and weight 0.
|
|
1134
|
+
"""
|
|
1135
|
+
if priority is not None and priority not in {"high", "medium"}:
|
|
1136
|
+
raise ValueError("priority must be one of high/medium")
|
|
1130
1137
|
if ak_ids is not None and not isinstance(ak_ids, list):
|
|
1131
1138
|
raise ValueError("ak_ids must be a list")
|
|
1132
1139
|
references = list(ak_ids or [])
|
|
@@ -1164,6 +1171,10 @@ class APIClient:
|
|
|
1164
1171
|
body["queue_id"] = effective_queue_id
|
|
1165
1172
|
if max_concurrency is not None:
|
|
1166
1173
|
body["max_concurrency"] = max_concurrency
|
|
1174
|
+
if priority is not None:
|
|
1175
|
+
body["priority"] = priority
|
|
1176
|
+
if priority_weight is not None:
|
|
1177
|
+
body["priority_weight"] = priority_weight
|
|
1167
1178
|
if eval_config is not None:
|
|
1168
1179
|
body["eval_config"] = eval_config
|
|
1169
1180
|
if model_base_url_collection is not None:
|
|
@@ -1881,9 +1892,15 @@ class APIClient:
|
|
|
1881
1892
|
meta_job_type: Optional[str] = None,
|
|
1882
1893
|
meta_teacher_direction: Optional[str] = None,
|
|
1883
1894
|
meta_train_stage: Optional[str] = None,
|
|
1895
|
+
benchmark: Optional[str] = None,
|
|
1896
|
+
priority: Optional[str] = None,
|
|
1897
|
+
priority_weight: Optional[int] = None,
|
|
1898
|
+
priority_update_mode: Optional[str] = None,
|
|
1884
1899
|
) -> dict:
|
|
1885
1900
|
"""Update group properties.
|
|
1886
1901
|
|
|
1902
|
+
``benchmark`` is omitted when None; pass an empty string to clear it.
|
|
1903
|
+
|
|
1887
1904
|
``tags``(`key:value` 数组)在客户端先与 Group 现有 tags 合并,再以
|
|
1888
1905
|
全量替换语义提交(服务端 PATCH 是整体替换);同名 key 覆盖,未提及
|
|
1889
1906
|
的 key 保留。服务端会从 tags 同步 meta_* 等派生字段。
|
|
@@ -1891,7 +1908,19 @@ class APIClient:
|
|
|
1891
1908
|
``meta_*`` 独立属性为部分更新(传了才改,不支持清除);新服务端
|
|
1892
1909
|
优先读属性,老服务端忽略属性——因此过渡期内同时也会将属性合并进
|
|
1893
1910
|
tags 轨(双写)。
|
|
1911
|
+
|
|
1912
|
+
Priority changes update the Group defaults. The default existing mode
|
|
1913
|
+
also updates all current Jobs, including PostProcess; incremental mode
|
|
1914
|
+
changes only the defaults for future Jobs. Updating priority alone uses
|
|
1915
|
+
weight 0; updating only weight preserves the current priority tier.
|
|
1894
1916
|
"""
|
|
1917
|
+
if priority is not None and priority not in {"high", "medium"}:
|
|
1918
|
+
raise ValueError("priority must be one of high/medium")
|
|
1919
|
+
if priority_update_mode is not None:
|
|
1920
|
+
if priority_update_mode not in {"existing", "incremental"}:
|
|
1921
|
+
raise ValueError("priority_update_mode must be one of existing/incremental")
|
|
1922
|
+
if priority is None and priority_weight is None:
|
|
1923
|
+
raise ValueError("priority_update_mode requires priority or priority_weight")
|
|
1895
1924
|
body: dict = {}
|
|
1896
1925
|
|
|
1897
1926
|
if max_concurrency is not None:
|
|
@@ -1906,6 +1935,14 @@ class APIClient:
|
|
|
1906
1935
|
body["model"] = model
|
|
1907
1936
|
if scaffold is not None:
|
|
1908
1937
|
body["scaffold"] = scaffold
|
|
1938
|
+
if benchmark is not None:
|
|
1939
|
+
body["benchmark"] = benchmark
|
|
1940
|
+
if priority is not None:
|
|
1941
|
+
body["priority"] = priority
|
|
1942
|
+
if priority_weight is not None:
|
|
1943
|
+
body["priority_weight"] = priority_weight
|
|
1944
|
+
if priority_update_mode is not None:
|
|
1945
|
+
body["priority_update_mode"] = priority_update_mode
|
|
1909
1946
|
meta_attr_tags = _merge_meta_tags(
|
|
1910
1947
|
None,
|
|
1911
1948
|
meta_model=meta_model,
|
|
@@ -642,7 +642,18 @@ def _print_formatted(data: dict, output_format: str) -> None:
|
|
|
642
642
|
import yaml
|
|
643
643
|
except ImportError as exc:
|
|
644
644
|
raise typer.BadParameter("--format yaml requires PyYAML to be installed") from exc
|
|
645
|
-
|
|
645
|
+
|
|
646
|
+
class LosslessDumper(yaml.SafeDumper):
|
|
647
|
+
pass
|
|
648
|
+
|
|
649
|
+
def represent_string(dumper, value):
|
|
650
|
+
# YAML normalizes literal NEL/line separators in unquoted scalars.
|
|
651
|
+
# Double quotes make the emitter escape them while keeping Chinese readable.
|
|
652
|
+
style = '"' if any(character in value for character in "\x85\u2028\u2029") else None
|
|
653
|
+
return dumper.represent_scalar("tag:yaml.org,2002:str", value, style=style)
|
|
654
|
+
|
|
655
|
+
LosslessDumper.add_representer(str, represent_string)
|
|
656
|
+
typer.echo(yaml.dump(data, Dumper=LosslessDumper, allow_unicode=True, sort_keys=False))
|
|
646
657
|
return
|
|
647
658
|
_print_json(data)
|
|
648
659
|
|
|
@@ -3219,12 +3230,12 @@ def job_create(
|
|
|
3219
3230
|
priority: Optional[str] = typer.Option(
|
|
3220
3231
|
None,
|
|
3221
3232
|
"--priority",
|
|
3222
|
-
help="Scheduling
|
|
3233
|
+
help="Scheduling tier: high or medium. Omit both priority flags to inherit Group defaults; otherwise an omitted tier is medium",
|
|
3223
3234
|
),
|
|
3224
3235
|
priority_weight: Optional[int] = typer.Option(
|
|
3225
3236
|
None,
|
|
3226
3237
|
"--priority-weight",
|
|
3227
|
-
help="
|
|
3238
|
+
help="Priority weight, 0-10. Omit both priority flags to inherit Group defaults; otherwise an omitted weight is 0",
|
|
3228
3239
|
),
|
|
3229
3240
|
resource_mode: Optional[str] = typer.Option(
|
|
3230
3241
|
None,
|
|
@@ -5457,6 +5468,18 @@ def group_create(
|
|
|
5457
5468
|
min=1,
|
|
5458
5469
|
help="Maximum concurrent jobs. Server default: 50.",
|
|
5459
5470
|
),
|
|
5471
|
+
priority: Optional[str] = typer.Option(
|
|
5472
|
+
None,
|
|
5473
|
+
"--priority",
|
|
5474
|
+
help="Default priority inherited by Jobs: high or medium (server default: medium)",
|
|
5475
|
+
),
|
|
5476
|
+
priority_weight: Optional[int] = typer.Option(
|
|
5477
|
+
None,
|
|
5478
|
+
"--priority-weight",
|
|
5479
|
+
min=0,
|
|
5480
|
+
max=10,
|
|
5481
|
+
help="Default priority weight inherited by Jobs, 0-10 (server default: 0)",
|
|
5482
|
+
),
|
|
5460
5483
|
eval_config: Optional[str] = typer.Option(
|
|
5461
5484
|
None, "--eval-config", help="Evaluation config (JSON)"
|
|
5462
5485
|
),
|
|
@@ -5569,6 +5592,8 @@ def group_create(
|
|
|
5569
5592
|
):
|
|
5570
5593
|
"""Create a Group."""
|
|
5571
5594
|
output_format = _normalize_output_format(output_format)
|
|
5595
|
+
if priority is not None and priority not in {"high", "medium"}:
|
|
5596
|
+
raise typer.BadParameter("--priority must be one of high/medium")
|
|
5572
5597
|
try:
|
|
5573
5598
|
for reference in ak_id or []:
|
|
5574
5599
|
validate_ak_id(reference)
|
|
@@ -5650,6 +5675,8 @@ def group_create(
|
|
|
5650
5675
|
checkpoint=checkpoint_dict,
|
|
5651
5676
|
benchmark=benchmark,
|
|
5652
5677
|
experiment=experiment,
|
|
5678
|
+
**({"priority": priority} if priority is not None else {}),
|
|
5679
|
+
**({"priority_weight": priority_weight} if priority_weight is not None else {}),
|
|
5653
5680
|
)
|
|
5654
5681
|
except ManagedAKProtocolError as exc:
|
|
5655
5682
|
_emit_error(str(exc))
|
|
@@ -5662,6 +5689,10 @@ def group_create(
|
|
|
5662
5689
|
print(f" ak_ids: {response_ak_ids(result)}")
|
|
5663
5690
|
if result.get("queue_id") is not None:
|
|
5664
5691
|
print(f" queue_id: {result.get('queue_id')}")
|
|
5692
|
+
if result.get("priority") is not None:
|
|
5693
|
+
print(f" priority: {result.get('priority')}")
|
|
5694
|
+
if result.get("priority_weight") is not None:
|
|
5695
|
+
print(f" priority_weight: {result.get('priority_weight')}")
|
|
5665
5696
|
if result.get("template") is not None:
|
|
5666
5697
|
print(f" template: {result.get('template')}")
|
|
5667
5698
|
if result.get("agenthub_revision") is not None:
|
|
@@ -6066,6 +6097,9 @@ def group_update(
|
|
|
6066
6097
|
scaffold: Optional[str] = typer.Option(
|
|
6067
6098
|
None, "--scaffold", "-s", help="Scaffold/agent name (benchmark perspective)"
|
|
6068
6099
|
),
|
|
6100
|
+
benchmark: Optional[str] = typer.Option(
|
|
6101
|
+
None, "--benchmark", help="Benchmark name; pass an empty string to clear"
|
|
6102
|
+
),
|
|
6069
6103
|
tags: Optional[str] = typer.Option(
|
|
6070
6104
|
None,
|
|
6071
6105
|
"--tags",
|
|
@@ -6085,14 +6119,40 @@ def group_update(
|
|
|
6085
6119
|
"--meta-train-stage",
|
|
6086
6120
|
help="Set meta_train_stage tag (options: ap meta-train-stage list)",
|
|
6087
6121
|
),
|
|
6122
|
+
priority: Optional[str] = typer.Option(
|
|
6123
|
+
None,
|
|
6124
|
+
"--priority",
|
|
6125
|
+
help="Group priority default: high or medium; --priority alone sets weight to 0",
|
|
6126
|
+
),
|
|
6127
|
+
priority_weight: Optional[int] = typer.Option(
|
|
6128
|
+
None,
|
|
6129
|
+
"--priority-weight",
|
|
6130
|
+
min=0,
|
|
6131
|
+
max=10,
|
|
6132
|
+
help="Group priority weight default, 0-10; weight alone preserves the current tier",
|
|
6133
|
+
),
|
|
6134
|
+
priority_update_mode: Optional[str] = typer.Option(
|
|
6135
|
+
None,
|
|
6136
|
+
"--priority-update-mode",
|
|
6137
|
+
help="existing updates defaults and all current Jobs (including PostProcess); incremental updates only defaults (server default: existing)",
|
|
6138
|
+
),
|
|
6088
6139
|
output_format: str = typer.Option(
|
|
6089
6140
|
None,
|
|
6090
6141
|
"--format",
|
|
6091
6142
|
help="Output format: plain/table/json/yaml (default: AP_FORMAT or command default)",
|
|
6092
6143
|
),
|
|
6093
6144
|
):
|
|
6094
|
-
"""Update Group properties."""
|
|
6145
|
+
"""Update Group properties and scheduling defaults inherited by Jobs."""
|
|
6095
6146
|
output_format = _normalize_output_format(output_format)
|
|
6147
|
+
if priority is not None and priority not in {"high", "medium"}:
|
|
6148
|
+
raise typer.BadParameter("--priority must be one of high/medium")
|
|
6149
|
+
if priority_update_mode is not None:
|
|
6150
|
+
if priority_update_mode not in {"existing", "incremental"}:
|
|
6151
|
+
raise typer.BadParameter("--priority-update-mode must be one of existing/incremental")
|
|
6152
|
+
if priority is None and priority_weight is None:
|
|
6153
|
+
raise typer.BadParameter(
|
|
6154
|
+
"--priority-update-mode requires --priority or --priority-weight"
|
|
6155
|
+
)
|
|
6096
6156
|
eval_config_dict = _parse_json_object(eval_config, "--eval-config")
|
|
6097
6157
|
model_base_url_collection_list = _parse_model_base_url_collection_option(
|
|
6098
6158
|
model_base_url_collection, model_base_url_file
|
|
@@ -6127,7 +6187,10 @@ def group_update(
|
|
|
6127
6187
|
dataset,
|
|
6128
6188
|
model_name,
|
|
6129
6189
|
scaffold,
|
|
6190
|
+
benchmark,
|
|
6130
6191
|
tags_list,
|
|
6192
|
+
priority,
|
|
6193
|
+
priority_weight,
|
|
6131
6194
|
)
|
|
6132
6195
|
):
|
|
6133
6196
|
raise typer.BadParameter("At least one field must be provided to update")
|
|
@@ -6141,7 +6204,15 @@ def group_update(
|
|
|
6141
6204
|
dataset=dataset,
|
|
6142
6205
|
model=model_name,
|
|
6143
6206
|
scaffold=scaffold,
|
|
6207
|
+
**({"benchmark": benchmark} if benchmark is not None else {}),
|
|
6144
6208
|
**({"tags": tags_list} if tags_list is not None else {}),
|
|
6209
|
+
**({"priority": priority} if priority is not None else {}),
|
|
6210
|
+
**({"priority_weight": priority_weight} if priority_weight is not None else {}),
|
|
6211
|
+
**(
|
|
6212
|
+
{"priority_update_mode": priority_update_mode}
|
|
6213
|
+
if priority_update_mode is not None
|
|
6214
|
+
else {}
|
|
6215
|
+
),
|
|
6145
6216
|
)
|
|
6146
6217
|
if output_format == "plain":
|
|
6147
6218
|
_print_group_action_plain(
|
|
@@ -6155,6 +6226,9 @@ def group_update(
|
|
|
6155
6226
|
"dataset",
|
|
6156
6227
|
"model",
|
|
6157
6228
|
"scaffold",
|
|
6229
|
+
"benchmark",
|
|
6230
|
+
"priority",
|
|
6231
|
+
"priority_weight",
|
|
6158
6232
|
"updated_at",
|
|
6159
6233
|
],
|
|
6160
6234
|
)
|
|
@@ -138,20 +138,31 @@ def _safe_identifier(value: Any) -> str | None:
|
|
|
138
138
|
|
|
139
139
|
|
|
140
140
|
class ManagedAKProtocolError(RuntimeError):
|
|
141
|
-
"""
|
|
141
|
+
"""An unconfirmed AK reference, with only safe receipt identities retained."""
|
|
142
142
|
|
|
143
143
|
def __init__(self, ak_id: str, response: Any):
|
|
144
144
|
self.ak_id = ak_id
|
|
145
|
-
self.response =
|
|
145
|
+
self.response: dict[str, Any] = {}
|
|
146
146
|
self.job_ids: list[str] = []
|
|
147
147
|
self.group_id = None
|
|
148
148
|
if isinstance(response, dict):
|
|
149
149
|
self.group_id = _safe_identifier(response.get("group_id"))
|
|
150
|
-
|
|
150
|
+
if self.group_id:
|
|
151
|
+
self.response["group_id"] = self.group_id
|
|
152
|
+
job_id = _safe_identifier(response.get("job_id"))
|
|
153
|
+
if job_id:
|
|
154
|
+
self.response["job_id"] = job_id
|
|
155
|
+
self.job_ids.append(job_id)
|
|
151
156
|
jobs = response.get("jobs")
|
|
152
157
|
if isinstance(jobs, list):
|
|
153
|
-
|
|
154
|
-
|
|
158
|
+
job_ids = [
|
|
159
|
+
value
|
|
160
|
+
for job in jobs
|
|
161
|
+
if isinstance(job, dict)
|
|
162
|
+
if (value := _safe_identifier(job.get("job_id")))
|
|
163
|
+
]
|
|
164
|
+
self.job_ids.extend(job_ids)
|
|
165
|
+
self.response["jobs"] = [{"job_id": value} for value in job_ids]
|
|
155
166
|
super().__init__(
|
|
156
167
|
f"Managed AK protocol mismatch: server did not acknowledge ak_id={ak_id}. "
|
|
157
168
|
f"Returned Job IDs: {self.job_ids}. Verify these jobs before resubmitting; "
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ap-client"
|
|
7
|
-
version = "0.6.0.
|
|
7
|
+
version = "0.6.0.dev2"
|
|
8
8
|
description = "Agent Platform API Client & CLI"
|
|
9
9
|
readme = { text = "A lightweight Python SDK and command line interface for Agent Platform. It provides helpers for configuring API access and managing templates, datasets, jobs, and groups.", content-type = "text/markdown" }
|
|
10
10
|
requires-python = ">=3.10"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|