1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
# frozen_string_literal: true
require 'mime/types'
module API
# MLFlow integration API, replicating the Rest API https://www.mlflow.org/docs/latest/rest-api.html#rest-api
module Ml
module Mlflow
class Runs < ::API::Base
feature_category :mlops
resource :runs do
desc 'Creates a Run.' do
success Entities::Ml::Mlflow::Run
detail 'MLFlow Runs map to GitLab Candidates. https://www.mlflow.org/docs/1.28.0/rest-api.html#create-run'
end
params do
requires :experiment_id, type: Integer,
desc: 'Id for the experiment, relative to the project'
optional :start_time, type: Integer,
desc: 'Unix timestamp in milliseconds of when the run started.',
default: 0
optional :user_id, type: String, desc: 'This will be ignored'
optional :tags, type: Array, desc: 'Tags are stored, but not displayed'
optional :run_name, type: String, desc: 'A name for this run'
end
post 'create', urgency: :low do
present candidate_repository.create!(experiment, params[:start_time], params[:tags], params[:run_name]),
with: Entities::Ml::Mlflow::GetRun, packages_url: packages_url
end
desc 'Gets an MLFlow Run, which maps to GitLab Candidates' do
success Entities::Ml::Mlflow::Run
detail 'https://www.mlflow.org/docs/1.28.0/rest-api.html#get-run'
end
params do
requires :run_id, type: String, desc: 'UUID of the candidate.'
optional :run_uuid, type: String, desc: 'This parameter is ignored'
end
get 'get', urgency: :low do
present candidate, with: Entities::Ml::Mlflow::GetRun, packages_url: packages_url
end
desc 'Searches runs/candidates within a project' do
success Entities::Ml::Mlflow::Run
detail 'https://www.mlflow.org/docs/1.28.0/rest-api.html#search-runs' \
'experiment_ids supports only a single experiment ID.' \
'Introduced in GitLab 16.4'
end
params do
requires :experiment_ids,
type: Array,
desc: 'IDs of the experiments to get searches from, relative to the project'
optional :max_results,
type: Integer,
desc: 'Maximum number of runs/candidates to fetch in a page. Default is 200, maximum in 1000',
default: 200
optional :order_by,
type: String,
desc: 'Order criteria. Can be by a column of the run/candidate (created_at, name) or by a metric if' \
'prefixed by `metrics`. Valid examples: `created_at`, `created_at DESC`, `metrics.my_metric DESC`' \
'Sorting by candidate parameter or metadata is not supported.',
default: 'created_at DESC'
optional :page_token,
type: String,
desc: 'Token for pagination'
end
post 'search', urgency: :low do
params[:experiment_id] = params[:experiment_ids][0]
max_results = [params[:max_results], 1000].min
finder_params = candidates_order_params(params)
finder = ::Projects::Ml::CandidateFinder.new(experiment, finder_params)
paginator = finder.execute.keyset_paginate(cursor: params[:page_token], per_page: max_results)
result = {
candidates: paginator.records,
next_page_token: paginator.cursor_for_next_page
}
present result, with: Entities::Ml::Mlflow::SearchRuns, packages_url: packages_url
end
desc 'Updates a Run.' do
success Entities::Ml::Mlflow::UpdateRun
detail 'MLFlow Runs map to GitLab Candidates. https://www.mlflow.org/docs/1.28.0/rest-api.html#update-run'
end
params do
requires :run_id, type: String, desc: 'UUID of the candidate.'
optional :status, type: String,
values: ::Ml::Candidate.statuses.keys.map(&:upcase),
desc: "Status of the run. Accepts: " \
"#{::Ml::Candidate.statuses.keys.map(&:upcase)}."
optional :end_time, type: Integer, desc: 'Ending time of the run'
end
post 'update', urgency: :low do
candidate_repository.update(candidate, params[:status], params[:end_time])
present candidate, with: Entities::Ml::Mlflow::UpdateRun, packages_url: packages_url
end
desc 'Logs a metric to a run.' do
summary 'Log a metric for a run. A metric is a key-value pair (string key, float value) with an ' \
'associated timestamp. Examples include the various metrics that represent ML model accuracy. ' \
'A metric can be logged multiple times.'
detail 'https://www.mlflow.org/docs/1.28.0/rest-api.html#log-metric'
end
params do
requires :run_id, type: String, desc: 'UUID of the run.'
requires :key, type: String, desc: 'Name for the metric.'
requires :value, type: Float, desc: 'Value of the metric.'
requires :timestamp, type: Integer, desc: 'Unix timestamp in milliseconds when metric was recorded'
optional :step, type: Integer, desc: 'Step at which the metric was recorded'
end
post 'log-metric', urgency: :low do
candidate_repository.add_metric!(
candidate,
params[:key],
params[:value],
params[:timestamp],
params[:step]
)
{}
end
desc 'Logs a parameter to a run.' do
summary 'Log a param used for a run. A param is a key-value pair (string key, string value). ' \
'Examples include hyperparameters used for ML model training and constant dates and values ' \
'used in an ETL pipeline. A param can be logged only once for a run, duplicate will be .' \
'ignored'
detail 'https://www.mlflow.org/docs/1.28.0/rest-api.html#log-param'
end
params do
requires :run_id, type: String, desc: 'UUID of the run.'
requires :key, type: String, desc: 'Name for the parameter.'
requires :value, type: String, desc: 'Value for the parameter.'
end
post 'log-parameter', urgency: :low do
bad_request! unless candidate_repository.add_param!(candidate, params[:key], params[:value])
{}
end
desc 'Sets a tag for a run.' do
summary 'Sets a tag for a run. '
detail 'https://www.mlflow.org/docs/1.28.0/rest-api.html#set-tag'
end
params do
requires :run_id, type: String, desc: 'UUID of the run.'
requires :key, type: String, desc: 'Name for the tag.'
requires :value, type: String, desc: 'Value for the tag.'
end
post 'set-tag', urgency: :low do
bad_request! unless candidate_repository.add_tag!(candidate, params[:key], params[:value])
{}
end
desc 'Logs multiple parameters and metrics.' do
summary 'Log a batch of metrics and params for a run. Validation errors will block the entire batch, ' \
'duplicate errors will be ignored.'
detail 'https://www.mlflow.org/docs/1.28.0/rest-api.html#log-param'
end
params do
requires :run_id, type: String, desc: 'UUID of the run.'
optional :metrics, type: Array, default: [] do
requires :key, type: String, desc: 'Name for the metric.'
requires :value, type: Float, desc: 'Value of the metric.'
requires :timestamp, type: Integer, desc: 'Unix timestamp in milliseconds when metric was recorded'
optional :step, type: Integer, desc: 'Step at which the metric was recorded'
end
optional :params, type: Array, default: [] do
requires :key, type: String, desc: 'Name for the metric.'
requires :value, type: String, desc: 'Value of the metric.'
end
end
post 'log-batch', urgency: :low do
candidate_repository.add_metrics(candidate, params[:metrics])
candidate_repository.add_params(candidate, params[:params])
candidate_repository.add_tags(candidate, params[:tags])
{}
end
end
end
end
end
end
|