repzo 1.0.292 → 1.0.293
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.
- package/changelog.md +28 -0
- package/lib/index.d.ts +244 -2
- package/lib/index.js +541 -0
- package/lib/types/index.d.ts +4530 -1
- package/package.json +1 -1
- package/src/index.ts +1270 -0
- package/src/oas/activity-ai-object-detection-session-frame.yaml +600 -0
- package/src/oas/ai-object-detection-assigned-missions.yaml +283 -0
- package/src/oas/ai-object-detection-assignment-rule.yaml +357 -0
- package/src/oas/ai-object-detection-category.yaml +338 -0
- package/src/oas/ai-object-detection-dataset.yaml +342 -0
- package/src/oas/ai-object-detection-detection-settings.yaml +410 -0
- package/src/oas/ai-object-detection-inference.yaml +818 -0
- package/src/oas/ai-object-detection-label-group.yaml +265 -0
- package/src/oas/ai-object-detection-label-report.yaml +366 -0
- package/src/oas/ai-object-detection-label.yaml +395 -0
- package/src/oas/ai-object-detection-metric-result.yaml +734 -0
- package/src/oas/ai-object-detection-metric.yaml +559 -0
- package/src/oas/ai-object-detection-mission-results.yaml +370 -0
- package/src/oas/ai-object-detection-mission-set.yaml +250 -0
- package/src/oas/ai-object-detection-mission.yaml +349 -0
- package/src/oas/ai-object-detection-model-version-epoch.yaml +214 -0
- package/src/oas/ai-object-detection-model-version-train-agent.yaml +88 -0
- package/src/oas/ai-object-detection-model-version.yaml +567 -0
- package/src/oas/ai-object-detection-model.yaml +369 -0
- package/src/oas/ai-object-detection-segment.yaml +301 -0
- package/src/oas/ai-object-detection-session-analysis.yaml +1306 -0
- package/src/oas/ai-object-detection-session-election.yaml +193 -0
- package/src/oas/ai-object-detection-session-insight.yaml +418 -0
- package/src/oas/ai-object-detection-session.yaml +840 -0
- package/src/oas/ai-object-detection-settings.yaml +249 -0
- package/src/oas/ai-object-detection-task.yaml +1007 -0
- package/src/oas/object-detection-analytics-report.yaml +674 -0
- package/src/types/index.ts +5156 -1
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
openapi: 3.0.3
|
|
2
|
+
info:
|
|
3
|
+
title: Repzo API - AI Object Detection Mission
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
description: |
|
|
6
|
+
**Missions** group planogram metrics (`/ai-object-detection-metric`)
|
|
7
|
+
with a WEIGHT each — the mission score is the weighted mean of the
|
|
8
|
+
metrics' effective result scores (0..1). A metric without a result on an
|
|
9
|
+
analysis counts as 0 (a demanded check that never ran must not score as
|
|
10
|
+
passed). Missions are grouped into mission SETS
|
|
11
|
+
(`/ai-object-detection-mission-set`) which assignment rules attach to
|
|
12
|
+
clients; a session started FROM a mission carries the mission's optional
|
|
13
|
+
detection `category`, which drives the auto-analysis.
|
|
14
|
+
|
|
15
|
+
**Scores read.** `GET ?scores_for=<analysisId>` resolves the assignment
|
|
16
|
+
rules against that analysis's session CLIENT and returns every enabled
|
|
17
|
+
mission with `assigned` (attached via a rule), `via_sets`,
|
|
18
|
+
`requirement_mode` (the strictest demand the matched rules place on it —
|
|
19
|
+
`not_required` / `submission_required` / `completion_required`; absent
|
|
20
|
+
when unassigned), the weighted `score` 0..1, `min_score` + `completed`
|
|
21
|
+
(a NON-ZERO score ≥ min_score; a zero score never completes — checks
|
|
22
|
+
that never ran are not achievements; `min_score` is the mission's
|
|
23
|
+
optional completion threshold, default 0) and the per-metric breakdown
|
|
24
|
+
(weight, effective score, `missing`). Resolution happens at read time —
|
|
25
|
+
recalculations and rule edits are reflected immediately, nothing is
|
|
26
|
+
persisted on the client. The STORED per-session outcome lives in
|
|
27
|
+
`/ai-object-detection-mission-results`.
|
|
28
|
+
|
|
29
|
+
**Validation.** Create AND update require `metrics` with at least one
|
|
30
|
+
row of `{ metric: <valid id>, weight: <number ≥ 0> }`; `min_score` must
|
|
31
|
+
be within 0..1 when given; `category` must be a valid id, or `null`/""
|
|
32
|
+
to clear it. Every violation is listed in one 400.
|
|
33
|
+
|
|
34
|
+
**Multi-tenancy & lifecycle.** Scoped by `company_namespace` (injected
|
|
35
|
+
from the caller's token; SDK callers may pass an explicit value on
|
|
36
|
+
create), soft-deleted via `disabled`. `enabled: false` hides the
|
|
37
|
+
mission from evaluation and `scores_for`. `PATCH` is not supported
|
|
38
|
+
(400 — use `PUT`). Admin-facing.
|
|
39
|
+
servers:
|
|
40
|
+
- url: https://sv.api.repzo.me
|
|
41
|
+
security:
|
|
42
|
+
- ApiKeyAuth: []
|
|
43
|
+
- JwtAuth: []
|
|
44
|
+
paths:
|
|
45
|
+
/ai-object-detection-mission:
|
|
46
|
+
get:
|
|
47
|
+
summary: List missions (or resolved scores for an analysis)
|
|
48
|
+
operationId: findMission
|
|
49
|
+
parameters:
|
|
50
|
+
- in: query
|
|
51
|
+
name: _id
|
|
52
|
+
schema:
|
|
53
|
+
oneOf:
|
|
54
|
+
- type: string
|
|
55
|
+
- type: array
|
|
56
|
+
items: { type: string }
|
|
57
|
+
- in: query
|
|
58
|
+
name: name
|
|
59
|
+
description: Exact name match.
|
|
60
|
+
schema:
|
|
61
|
+
oneOf:
|
|
62
|
+
- type: string
|
|
63
|
+
- type: array
|
|
64
|
+
items: { type: string }
|
|
65
|
+
- in: query
|
|
66
|
+
name: search
|
|
67
|
+
description: Case-insensitive substring search on `name`.
|
|
68
|
+
schema: { type: string }
|
|
69
|
+
- in: query
|
|
70
|
+
name: enabled
|
|
71
|
+
schema: { type: boolean }
|
|
72
|
+
- in: query
|
|
73
|
+
name: disabled
|
|
74
|
+
description: "Include soft-deleted missions (`true`) or only live ones (`false`). Omitted = no filter."
|
|
75
|
+
schema: { type: boolean }
|
|
76
|
+
- in: query
|
|
77
|
+
name: from_updatedAt
|
|
78
|
+
schema: { type: number }
|
|
79
|
+
- in: query
|
|
80
|
+
name: to_updatedAt
|
|
81
|
+
schema: { type: number }
|
|
82
|
+
- in: query
|
|
83
|
+
name: from_createdAt
|
|
84
|
+
schema: { type: number }
|
|
85
|
+
- in: query
|
|
86
|
+
name: to_createdAt
|
|
87
|
+
schema: { type: number }
|
|
88
|
+
- in: query
|
|
89
|
+
name: scores_for
|
|
90
|
+
description: |
|
|
91
|
+
Analysis _id — returns RESOLVED MISSION SCORES for it instead of
|
|
92
|
+
documents (see `MissionScores`). `completed` = a NON-ZERO score ≥
|
|
93
|
+
the mission's min_score (computed at read, never stamped). All
|
|
94
|
+
other filters and pagination are ignored in this mode.
|
|
95
|
+
schema: { type: string }
|
|
96
|
+
- in: query
|
|
97
|
+
name: per_page
|
|
98
|
+
schema: { type: integer, minimum: 1 }
|
|
99
|
+
- in: query
|
|
100
|
+
name: page
|
|
101
|
+
schema: { type: integer, minimum: 1 }
|
|
102
|
+
responses:
|
|
103
|
+
"200":
|
|
104
|
+
description: "Paginated documents (newest `_id` first), or `MissionScores` when `scores_for` is given."
|
|
105
|
+
content:
|
|
106
|
+
application/json:
|
|
107
|
+
schema:
|
|
108
|
+
oneOf:
|
|
109
|
+
- $ref: "#/components/schemas/MissionFindResult"
|
|
110
|
+
- $ref: "#/components/schemas/MissionScores"
|
|
111
|
+
post:
|
|
112
|
+
summary: Create a mission
|
|
113
|
+
operationId: createMission
|
|
114
|
+
requestBody:
|
|
115
|
+
required: true
|
|
116
|
+
content:
|
|
117
|
+
application/json:
|
|
118
|
+
schema:
|
|
119
|
+
$ref: "#/components/schemas/MissionCreateBody"
|
|
120
|
+
responses:
|
|
121
|
+
"201":
|
|
122
|
+
description: The created document.
|
|
123
|
+
content:
|
|
124
|
+
application/json:
|
|
125
|
+
schema:
|
|
126
|
+
$ref: "#/components/schemas/Mission"
|
|
127
|
+
"400":
|
|
128
|
+
description: Validation failed — the message lists every violation.
|
|
129
|
+
/ai-object-detection-mission/{id}:
|
|
130
|
+
get:
|
|
131
|
+
summary: Get a mission
|
|
132
|
+
operationId: getMission
|
|
133
|
+
parameters:
|
|
134
|
+
- in: path
|
|
135
|
+
name: id
|
|
136
|
+
required: true
|
|
137
|
+
schema: { type: string }
|
|
138
|
+
responses:
|
|
139
|
+
"200":
|
|
140
|
+
description: The document.
|
|
141
|
+
content:
|
|
142
|
+
application/json:
|
|
143
|
+
schema:
|
|
144
|
+
$ref: "#/components/schemas/Mission"
|
|
145
|
+
"400":
|
|
146
|
+
description: Not found.
|
|
147
|
+
put:
|
|
148
|
+
summary: Update a mission (re-validated)
|
|
149
|
+
description: "Same validation as create — `metrics` (≥ 1 row) is required again. `category: null` clears the category; omitting it leaves the stored value. Set `disabled: true` to soft-delete."
|
|
150
|
+
operationId: updateMission
|
|
151
|
+
parameters:
|
|
152
|
+
- in: path
|
|
153
|
+
name: id
|
|
154
|
+
required: true
|
|
155
|
+
schema: { type: string }
|
|
156
|
+
requestBody:
|
|
157
|
+
required: true
|
|
158
|
+
content:
|
|
159
|
+
application/json:
|
|
160
|
+
schema:
|
|
161
|
+
$ref: "#/components/schemas/MissionUpdateBody"
|
|
162
|
+
responses:
|
|
163
|
+
"200":
|
|
164
|
+
description: The updated document.
|
|
165
|
+
content:
|
|
166
|
+
application/json:
|
|
167
|
+
schema:
|
|
168
|
+
$ref: "#/components/schemas/Mission"
|
|
169
|
+
"400":
|
|
170
|
+
description: Validation failed.
|
|
171
|
+
"404":
|
|
172
|
+
description: Not found.
|
|
173
|
+
delete:
|
|
174
|
+
summary: Soft-delete a mission
|
|
175
|
+
operationId: removeMission
|
|
176
|
+
parameters:
|
|
177
|
+
- in: path
|
|
178
|
+
name: id
|
|
179
|
+
required: true
|
|
180
|
+
schema: { type: string }
|
|
181
|
+
responses:
|
|
182
|
+
"200":
|
|
183
|
+
description: The disabled document.
|
|
184
|
+
content:
|
|
185
|
+
application/json:
|
|
186
|
+
schema:
|
|
187
|
+
$ref: "#/components/schemas/Mission"
|
|
188
|
+
"404":
|
|
189
|
+
description: Not found.
|
|
190
|
+
components:
|
|
191
|
+
securitySchemes:
|
|
192
|
+
ApiKeyAuth:
|
|
193
|
+
type: apiKey
|
|
194
|
+
in: header
|
|
195
|
+
name: api-key
|
|
196
|
+
JwtAuth:
|
|
197
|
+
type: apiKey
|
|
198
|
+
in: header
|
|
199
|
+
name: Authorization
|
|
200
|
+
schemas:
|
|
201
|
+
UserStamp:
|
|
202
|
+
type: object
|
|
203
|
+
description: "Who created / last edited the document (server-stamped from the token)."
|
|
204
|
+
properties:
|
|
205
|
+
_id: { type: string }
|
|
206
|
+
name: { type: string }
|
|
207
|
+
type:
|
|
208
|
+
type: string
|
|
209
|
+
enum: [admin, rep, client, tenant]
|
|
210
|
+
admin: { type: string }
|
|
211
|
+
rep: { type: string }
|
|
212
|
+
client: { type: string }
|
|
213
|
+
tenant: { type: string }
|
|
214
|
+
MissionMetricRow:
|
|
215
|
+
type: object
|
|
216
|
+
required: [metric, weight]
|
|
217
|
+
properties:
|
|
218
|
+
metric:
|
|
219
|
+
type: string
|
|
220
|
+
description: Metric id (`/ai-object-detection-metric`).
|
|
221
|
+
weight:
|
|
222
|
+
type: number
|
|
223
|
+
minimum: 0
|
|
224
|
+
description: Weight in the weighted mean.
|
|
225
|
+
MissionFields:
|
|
226
|
+
type: object
|
|
227
|
+
properties:
|
|
228
|
+
name: { type: string }
|
|
229
|
+
description: { type: string }
|
|
230
|
+
metrics:
|
|
231
|
+
type: array
|
|
232
|
+
minItems: 1
|
|
233
|
+
description: "Weighted metric rows — the mission's composition (required, ≥ 1 row)."
|
|
234
|
+
items:
|
|
235
|
+
$ref: "#/components/schemas/MissionMetricRow"
|
|
236
|
+
min_score:
|
|
237
|
+
type: number
|
|
238
|
+
minimum: 0
|
|
239
|
+
maximum: 1
|
|
240
|
+
default: 0
|
|
241
|
+
description: 'Optional completion threshold: the mission counts as COMPLETED on an analysis when its NON-ZERO weighted score ≥ this. 0 (default) = any non-zero score completes. null/"" = leave default.'
|
|
242
|
+
category:
|
|
243
|
+
type: string
|
|
244
|
+
nullable: true
|
|
245
|
+
description: "Optional detection category (`/ai-object-detection-category`). The mobile stamps it on a session started FROM this mission, so the category pipeline drives the auto-analysis. null clears it."
|
|
246
|
+
enabled: { type: boolean, default: true }
|
|
247
|
+
MissionCreateBody:
|
|
248
|
+
allOf:
|
|
249
|
+
- $ref: "#/components/schemas/MissionFields"
|
|
250
|
+
- type: object
|
|
251
|
+
required: [name, metrics]
|
|
252
|
+
properties:
|
|
253
|
+
company_namespace:
|
|
254
|
+
type: array
|
|
255
|
+
items: { type: string }
|
|
256
|
+
description: Optional tenant namespace override for SDK callers.
|
|
257
|
+
MissionUpdateBody:
|
|
258
|
+
allOf:
|
|
259
|
+
- $ref: "#/components/schemas/MissionFields"
|
|
260
|
+
- type: object
|
|
261
|
+
required: [metrics]
|
|
262
|
+
properties:
|
|
263
|
+
disabled:
|
|
264
|
+
type: boolean
|
|
265
|
+
description: Soft-delete flag.
|
|
266
|
+
Mission:
|
|
267
|
+
allOf:
|
|
268
|
+
- $ref: "#/components/schemas/MissionFields"
|
|
269
|
+
- type: object
|
|
270
|
+
properties:
|
|
271
|
+
_id: { type: string }
|
|
272
|
+
disabled: { type: boolean }
|
|
273
|
+
creator:
|
|
274
|
+
$ref: "#/components/schemas/UserStamp"
|
|
275
|
+
editor:
|
|
276
|
+
$ref: "#/components/schemas/UserStamp"
|
|
277
|
+
company_namespace:
|
|
278
|
+
type: array
|
|
279
|
+
items: { type: string }
|
|
280
|
+
createdAt: { type: string, format: date-time }
|
|
281
|
+
updatedAt: { type: string, format: date-time }
|
|
282
|
+
MissionScores:
|
|
283
|
+
type: object
|
|
284
|
+
description: "Response of `GET ?scores_for=<analysisId>` — every enabled mission scored against the analysis, assigned ones first, then by name."
|
|
285
|
+
properties:
|
|
286
|
+
analysis: { type: string }
|
|
287
|
+
client:
|
|
288
|
+
type: string
|
|
289
|
+
nullable: true
|
|
290
|
+
description: The analysis's session client (null when the session has none).
|
|
291
|
+
missions:
|
|
292
|
+
type: array
|
|
293
|
+
items:
|
|
294
|
+
type: object
|
|
295
|
+
properties:
|
|
296
|
+
_id: { type: string }
|
|
297
|
+
name: { type: string }
|
|
298
|
+
assigned:
|
|
299
|
+
type: boolean
|
|
300
|
+
description: An enabled assignment rule attaches a set containing this mission to the client.
|
|
301
|
+
via_sets:
|
|
302
|
+
type: array
|
|
303
|
+
items: { type: string }
|
|
304
|
+
description: Names of the assigned sets this mission arrived through.
|
|
305
|
+
requirement_mode:
|
|
306
|
+
type: string
|
|
307
|
+
enum: [not_required, submission_required, completion_required]
|
|
308
|
+
description: Strictest demand the matched rules place on it; absent when unassigned.
|
|
309
|
+
score:
|
|
310
|
+
type: number
|
|
311
|
+
description: Weighted mean 0..1 of the metrics' effective scores (missing metrics count 0).
|
|
312
|
+
min_score: { type: number }
|
|
313
|
+
completed:
|
|
314
|
+
type: boolean
|
|
315
|
+
description: NON-ZERO score ≥ min_score.
|
|
316
|
+
metrics:
|
|
317
|
+
type: array
|
|
318
|
+
items:
|
|
319
|
+
type: object
|
|
320
|
+
properties:
|
|
321
|
+
metric: { type: string }
|
|
322
|
+
name:
|
|
323
|
+
type: string
|
|
324
|
+
description: Metric-name snapshot from its result (absent when missing).
|
|
325
|
+
weight: { type: number }
|
|
326
|
+
score:
|
|
327
|
+
type: number
|
|
328
|
+
description: Effective 0..1 score of the metric's result; absent when missing.
|
|
329
|
+
missing:
|
|
330
|
+
type: boolean
|
|
331
|
+
description: The metric has no result on this analysis.
|
|
332
|
+
MissionFindResult:
|
|
333
|
+
type: object
|
|
334
|
+
description: Standard paginated result envelope.
|
|
335
|
+
properties:
|
|
336
|
+
data:
|
|
337
|
+
type: array
|
|
338
|
+
items:
|
|
339
|
+
$ref: "#/components/schemas/Mission"
|
|
340
|
+
total_result: { type: number }
|
|
341
|
+
current_count: { type: number }
|
|
342
|
+
total_pages: { type: number }
|
|
343
|
+
current_page: { type: number }
|
|
344
|
+
per_page: { type: number }
|
|
345
|
+
first_page_url: { type: string }
|
|
346
|
+
last_page_url: { type: string }
|
|
347
|
+
next_page_url: { type: string, nullable: true }
|
|
348
|
+
prev_page_url: { type: string, nullable: true }
|
|
349
|
+
path: { type: string }
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
openapi: 3.0.3
|
|
2
|
+
info:
|
|
3
|
+
title: Repzo API - Object Detection Model Version Epochs
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
description: |
|
|
6
|
+
Per-epoch training telemetry for one object-detection model version — the
|
|
7
|
+
series behind the training curves.
|
|
8
|
+
|
|
9
|
+
**Where the rows come from.** They are NOT written through this service.
|
|
10
|
+
The Ultralytics training run (the "Run on agent" snippet from
|
|
11
|
+
`ai-object-detection-model-version-train-agent`) streams metrics to
|
|
12
|
+
`POST /ul-hub/v1/models/:id` on every epoch via the Ultralytics HUB client;
|
|
13
|
+
that ingest de-slashes Ultralytics' native keys (`train/box_loss` →
|
|
14
|
+
`train_loss_metrics.box_loss`, `metrics/mAP50-95(B)` →
|
|
15
|
+
`performance_metrics.mAP50_95_B`) and upserts one row per epoch index. This
|
|
16
|
+
service is strictly READ-ONLY — create/update/patch/remove all return 400.
|
|
17
|
+
|
|
18
|
+
**Who calls it.** Back-office admins via the dashboard's version detail
|
|
19
|
+
screen (Metrics tab). Scoped by `company_namespace[]`.
|
|
20
|
+
|
|
21
|
+
**Shape of the response.** `find` is NOT paginated: a curve needs every
|
|
22
|
+
point and a run is bounded (hundreds of epochs at most), so the full series
|
|
23
|
+
is returned in `_index` order alongside a derived `summary` (best epoch,
|
|
24
|
+
best vs final metrics, architecture cost, final generalization gap).
|
|
25
|
+
`per_page` / `page` / `sort` are ignored. The summary is computed on read,
|
|
26
|
+
so versions trained before this endpoint existed summarize correctly too.
|
|
27
|
+
|
|
28
|
+
**Key relationships.** `model_version` → `ai-object-detection-model-version`.
|
|
29
|
+
The same best-epoch roll-up is snapshotted onto that version's `metrics` /
|
|
30
|
+
`model_stats` when its weights upload completes.
|
|
31
|
+
servers:
|
|
32
|
+
- url: https://sv.api.repzo.me
|
|
33
|
+
security:
|
|
34
|
+
- ApiKeyAuth: []
|
|
35
|
+
- JwtAuth: []
|
|
36
|
+
paths:
|
|
37
|
+
/ai-object-detection-model-version-epoch:
|
|
38
|
+
get:
|
|
39
|
+
summary: List every reported epoch of one training run
|
|
40
|
+
description: |
|
|
41
|
+
Returns the full epoch series for `model_version`, ordered by `_index`
|
|
42
|
+
ascending, plus a derived `summary`. Not paginated.
|
|
43
|
+
operationId: findAiObjectDetectionModelVersionEpochs
|
|
44
|
+
parameters:
|
|
45
|
+
- in: query
|
|
46
|
+
name: model_version
|
|
47
|
+
required: true
|
|
48
|
+
description: |
|
|
49
|
+
The `ai-object-detection-model-version` `_id` whose run to read.
|
|
50
|
+
Required — epochs are only meaningful per version (400 without it).
|
|
51
|
+
schema: { type: string }
|
|
52
|
+
example: 6a6e0687de060479c01c9e49
|
|
53
|
+
- in: query
|
|
54
|
+
name: _id
|
|
55
|
+
description: "Filter to specific epoch row id(s). Pass once or as `?_id[]=...`."
|
|
56
|
+
schema:
|
|
57
|
+
oneOf:
|
|
58
|
+
- type: string
|
|
59
|
+
- type: array
|
|
60
|
+
items: { type: string }
|
|
61
|
+
- in: query
|
|
62
|
+
name: _index
|
|
63
|
+
description: Filter to one or more epoch indexes (0-based).
|
|
64
|
+
schema:
|
|
65
|
+
oneOf:
|
|
66
|
+
- type: integer
|
|
67
|
+
minimum: 0
|
|
68
|
+
- type: array
|
|
69
|
+
items: { type: integer, minimum: 0 }
|
|
70
|
+
- in: query
|
|
71
|
+
name: type
|
|
72
|
+
description: Payload kind reported by the trainer. Only `metrics` today.
|
|
73
|
+
schema: { type: string, enum: [metrics] }
|
|
74
|
+
- in: query
|
|
75
|
+
name: disabled
|
|
76
|
+
description: Include disabled rows. Defaults to `false`.
|
|
77
|
+
schema: { type: boolean, default: false }
|
|
78
|
+
responses:
|
|
79
|
+
"200":
|
|
80
|
+
description: The ordered epoch series and its derived summary.
|
|
81
|
+
content:
|
|
82
|
+
application/json:
|
|
83
|
+
schema:
|
|
84
|
+
$ref: "#/components/schemas/EpochFindResult"
|
|
85
|
+
"400":
|
|
86
|
+
description: "`model_version` was not supplied."
|
|
87
|
+
/ai-object-detection-model-version-epoch/{id}:
|
|
88
|
+
get:
|
|
89
|
+
summary: Get one epoch row
|
|
90
|
+
operationId: getAiObjectDetectionModelVersionEpoch
|
|
91
|
+
parameters:
|
|
92
|
+
- in: path
|
|
93
|
+
name: id
|
|
94
|
+
required: true
|
|
95
|
+
schema: { type: string }
|
|
96
|
+
responses:
|
|
97
|
+
"200":
|
|
98
|
+
description: The epoch document.
|
|
99
|
+
content:
|
|
100
|
+
application/json:
|
|
101
|
+
schema:
|
|
102
|
+
$ref: "#/components/schemas/EpochSchema"
|
|
103
|
+
"400":
|
|
104
|
+
description: No epoch with that id.
|
|
105
|
+
components:
|
|
106
|
+
securitySchemes:
|
|
107
|
+
ApiKeyAuth:
|
|
108
|
+
type: apiKey
|
|
109
|
+
in: header
|
|
110
|
+
name: api-key
|
|
111
|
+
description: |
|
|
112
|
+
Server-issued API key. Also accepted via the `x-api-key` header or the
|
|
113
|
+
`?apiKey=` query parameter as fallbacks.
|
|
114
|
+
JwtAuth:
|
|
115
|
+
type: apiKey
|
|
116
|
+
in: header
|
|
117
|
+
name: Authorization
|
|
118
|
+
description: |
|
|
119
|
+
Raw JWT in the `Authorization` header — **no `Bearer ` prefix**.
|
|
120
|
+
Obtained from `POST /authenticate` (admin / rep / client login).
|
|
121
|
+
schemas:
|
|
122
|
+
LossMetrics:
|
|
123
|
+
type: object
|
|
124
|
+
description: Ultralytics loss components for one epoch.
|
|
125
|
+
properties:
|
|
126
|
+
box_loss: { type: number, description: Bounding-box regression loss. }
|
|
127
|
+
cls_loss: { type: number, description: Classification loss. }
|
|
128
|
+
dfl_loss: { type: number, description: Distribution focal loss. }
|
|
129
|
+
PerformanceMetrics:
|
|
130
|
+
type: object
|
|
131
|
+
description: |
|
|
132
|
+
Validation metrics for one epoch. The `_B` suffix is Ultralytics' own —
|
|
133
|
+
it denotes the Box (detection) task, as opposed to segmentation/pose.
|
|
134
|
+
properties:
|
|
135
|
+
precision_B: { type: number }
|
|
136
|
+
recall_B: { type: number }
|
|
137
|
+
mAP50_B:
|
|
138
|
+
type: number
|
|
139
|
+
description: mAP at IoU 0.50 — the lenient, headline number.
|
|
140
|
+
mAP50_95_B:
|
|
141
|
+
type: number
|
|
142
|
+
description: |
|
|
143
|
+
mAP averaged over IoU 0.50:0.95 — the strict number `best.pt` is
|
|
144
|
+
selected on.
|
|
145
|
+
ModelStats:
|
|
146
|
+
type: object
|
|
147
|
+
description: |
|
|
148
|
+
Architecture cost. Ultralytics reports it only on some epochs, so it can
|
|
149
|
+
be absent on any individual row.
|
|
150
|
+
properties:
|
|
151
|
+
parameters: { type: integer, description: Total weight count. }
|
|
152
|
+
GFLOPs: { type: number, description: Forward-pass cost per image. }
|
|
153
|
+
speed_PyTorch_ms:
|
|
154
|
+
type: number
|
|
155
|
+
description: Per-image PyTorch inference latency measured during validation.
|
|
156
|
+
EpochSchema:
|
|
157
|
+
type: object
|
|
158
|
+
properties:
|
|
159
|
+
_id: { type: string }
|
|
160
|
+
_index:
|
|
161
|
+
{
|
|
162
|
+
type: integer,
|
|
163
|
+
description: "0-based epoch number; unique per `model_version`.",
|
|
164
|
+
}
|
|
165
|
+
model_version: { type: string }
|
|
166
|
+
type: { type: string, enum: [metrics] }
|
|
167
|
+
train_loss_metrics: { $ref: "#/components/schemas/LossMetrics" }
|
|
168
|
+
val_loss_metrics: { $ref: "#/components/schemas/LossMetrics" }
|
|
169
|
+
performance_metrics: { $ref: "#/components/schemas/PerformanceMetrics" }
|
|
170
|
+
model_stats: { $ref: "#/components/schemas/ModelStats" }
|
|
171
|
+
disabled: { type: boolean }
|
|
172
|
+
company_namespace: { type: array, items: { type: string } }
|
|
173
|
+
createdAt: { type: string, format: date-time }
|
|
174
|
+
updatedAt: { type: string, format: date-time }
|
|
175
|
+
EpochPerformanceRollup:
|
|
176
|
+
type: object
|
|
177
|
+
properties:
|
|
178
|
+
mAP50: { type: number }
|
|
179
|
+
mAP50_95: { type: number }
|
|
180
|
+
precision: { type: number }
|
|
181
|
+
recall: { type: number }
|
|
182
|
+
EpochSummary:
|
|
183
|
+
type: object
|
|
184
|
+
description: Derived on read from the returned series.
|
|
185
|
+
properties:
|
|
186
|
+
epochs_reported:
|
|
187
|
+
type: integer
|
|
188
|
+
description: |
|
|
189
|
+
How many epochs the trainer has reported so far — less than the
|
|
190
|
+
configured `epochs` while a run is still in flight.
|
|
191
|
+
best_epoch:
|
|
192
|
+
type: integer
|
|
193
|
+
description: "`_index` of the highest-mAP50-95 epoch — what `best.pt` holds."
|
|
194
|
+
best: { $ref: "#/components/schemas/EpochPerformanceRollup" }
|
|
195
|
+
final:
|
|
196
|
+
allOf:
|
|
197
|
+
- $ref: "#/components/schemas/EpochPerformanceRollup"
|
|
198
|
+
- description: Last reported epoch — diverges from `best` when the run overfit.
|
|
199
|
+
model_stats: { $ref: "#/components/schemas/ModelStats" }
|
|
200
|
+
final_generalization_gap:
|
|
201
|
+
type: number
|
|
202
|
+
description: |
|
|
203
|
+
Total validation loss minus total training loss at the final epoch.
|
|
204
|
+
Positive and widening is the classic overfitting signature — the run
|
|
205
|
+
kept fitting the training set while validation stopped improving.
|
|
206
|
+
EpochFindResult:
|
|
207
|
+
type: object
|
|
208
|
+
properties:
|
|
209
|
+
data:
|
|
210
|
+
type: array
|
|
211
|
+
description: Every reported epoch, ascending by `_index`.
|
|
212
|
+
items: { $ref: "#/components/schemas/EpochSchema" }
|
|
213
|
+
total_result: { type: integer }
|
|
214
|
+
summary: { $ref: "#/components/schemas/EpochSummary" }
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
openapi: 3.0.3
|
|
2
|
+
info:
|
|
3
|
+
title: Repzo API - AI Object Detection Model Version Train Agent
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
description: |
|
|
6
|
+
Returns a **YOLO / Ultralytics bootstrap code snippet** for a given
|
|
7
|
+
`ai-object-detection-model-version` — the script a self-hosted trainer runs to
|
|
8
|
+
train against Repzo's own server (via the `ul-hub` Ultralytics-Hub-compatible
|
|
9
|
+
endpoints). The response is a list of ordered `steps[]`, each a
|
|
10
|
+
`code_message` to paste into a terminal / notebook: (1) `pip install` the
|
|
11
|
+
pinned ultralytics release, (2) point the HUB client at Repzo, `hub.login`
|
|
12
|
+
with an API key and `YOLO("<hub>/models/<version-id>").train()` — which
|
|
13
|
+
resolves the version's `initial_weight`, dataset zip and `train_settings`,
|
|
14
|
+
streams per-epoch metrics into `ai-object-detection-model-version-epoch`
|
|
15
|
+
and uploads `best.pt` / `last.pt` (flipping the version to `trained`), and
|
|
16
|
+
(3) POST the run's plots, `results.csv` and `args.yaml` to
|
|
17
|
+
`/ul-hub/v1/models/{id}/upload?type=artifacts`, because the HUB client sends
|
|
18
|
+
only weights.
|
|
19
|
+
|
|
20
|
+
**The ultralytics version is pinned, deliberately.** Release `8.4.115`
|
|
21
|
+
deleted the `ultralytics.hub` package: models no longer load from HUB URLs
|
|
22
|
+
and training no longer manages HUB sessions or heartbeats. This whole flow
|
|
23
|
+
rides that client, so on `8.4.115+` the script fails at import and no
|
|
24
|
+
results are ever reported. The snippet installs `ultralytics==8.4.114` (the
|
|
25
|
+
last release shipping the client) and surfaces it as `ultralytics_version`;
|
|
26
|
+
it must not be "upgraded" with `-U`.
|
|
27
|
+
|
|
28
|
+
**Who calls it.** Back-office admins setting up training. Stateless — it
|
|
29
|
+
only reads the model version. Only `GET /{id}` (`get`) is implemented —
|
|
30
|
+
`find`, `create`, `update`, `patch`, `remove` return 400. Scoped by
|
|
31
|
+
`company_namespace[]` through the version lookup.
|
|
32
|
+
servers:
|
|
33
|
+
- url: https://sv.api.repzo.me
|
|
34
|
+
security:
|
|
35
|
+
- ApiKeyAuth: []
|
|
36
|
+
- JwtAuth: []
|
|
37
|
+
paths:
|
|
38
|
+
/ai-object-detection-model-version-train-agent/{id}:
|
|
39
|
+
get:
|
|
40
|
+
summary: Get the training bootstrap snippet for a version
|
|
41
|
+
description: "`{id}` is the `ai-object-detection-model-version` id. The snippet embeds that id, the version's `initial_weight`, and the Repzo `ul-hub` base URLs."
|
|
42
|
+
operationId: getAiObjectDetectionTrainAgent
|
|
43
|
+
parameters:
|
|
44
|
+
[{ in: path, name: id, required: true, schema: { type: string } }]
|
|
45
|
+
responses:
|
|
46
|
+
"200":
|
|
47
|
+
description: The bootstrap steps for training the model version.
|
|
48
|
+
content:
|
|
49
|
+
application/json:
|
|
50
|
+
schema: { $ref: "#/components/schemas/TrainAgentSnippet" }
|
|
51
|
+
"400":
|
|
52
|
+
description: "Model version not found (or the caller tried `find`/`create`/`update`/`patch`/`remove`)."
|
|
53
|
+
components:
|
|
54
|
+
securitySchemes:
|
|
55
|
+
ApiKeyAuth:
|
|
56
|
+
{
|
|
57
|
+
type: apiKey,
|
|
58
|
+
in: header,
|
|
59
|
+
name: api-key,
|
|
60
|
+
description: "Server-issued API key. Also `x-api-key` header or `?apiKey=` query.",
|
|
61
|
+
}
|
|
62
|
+
JwtAuth:
|
|
63
|
+
{
|
|
64
|
+
type: apiKey,
|
|
65
|
+
in: header,
|
|
66
|
+
name: Authorization,
|
|
67
|
+
description: "Raw JWT — no `Bearer ` prefix. From `POST /authenticate`.",
|
|
68
|
+
}
|
|
69
|
+
schemas:
|
|
70
|
+
TrainAgentStep:
|
|
71
|
+
type: object
|
|
72
|
+
required: [code_message]
|
|
73
|
+
properties:
|
|
74
|
+
code_message:
|
|
75
|
+
type: string
|
|
76
|
+
description: A ready-to-run shell / Python snippet (multi-line).
|
|
77
|
+
TrainAgentSnippet:
|
|
78
|
+
type: object
|
|
79
|
+
required: [steps]
|
|
80
|
+
properties:
|
|
81
|
+
steps:
|
|
82
|
+
type: array
|
|
83
|
+
description: "Ordered: pin-install ultralytics, train against Repzo's ul-hub, upload plots + args."
|
|
84
|
+
items: { $ref: "#/components/schemas/TrainAgentStep" }
|
|
85
|
+
ultralytics_version:
|
|
86
|
+
type: string
|
|
87
|
+
description: "The pinned ultralytics release the snippet installs (currently `8.4.114`)."
|
|
88
|
+
example: "8.4.114"
|