Skip to content

Commit 6382569

Browse files
committed
Reimplementing experiment service: createexperiment and getexperiment
1 parent 397eede commit 6382569

File tree

3 files changed

+152
-58
lines changed

3 files changed

+152
-58
lines changed

src/MLFlowClient.jl

Lines changed: 9 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -20,68 +20,19 @@ using JSON
2020
using ShowCases
2121
using FilePathsBase: AbstractPath
2222

23-
include("types/mlflow.jl")
24-
export
25-
MLFlow
26-
23+
include("types/tag.jl")
24+
include("types/enums.jl")
25+
include("types/dataset.jl")
26+
include("types/artifact.jl")
27+
include("types/model_version.jl")
28+
include("types/registered_model.jl")
2729
include("types/experiment.jl")
28-
export
29-
MLFlowExperiment
30-
3130
include("types/run.jl")
32-
export
33-
MLFlowRunStatus,
34-
MLFlowRunInfo,
35-
MLFlowRunDataMetric,
36-
MLFlowRunDataParam,
37-
MLFlowRunData,
38-
MLFlowRun,
39-
get_info,
40-
get_data,
41-
get_run_id,
42-
get_params
43-
44-
include("types/artifact.jl")
45-
export
46-
MLFlowArtifactFileInfo,
47-
MLFlowArtifactDirInfo,
48-
get_path,
49-
get_size
50-
51-
include("api.jl")
31+
include("types/mlflow.jl")
5232

5333
include("utils.jl")
54-
export
55-
generatefilterfromparams
56-
generatefilterfromattributes
57-
generatefilterfromentity_type
58-
59-
include("experiments.jl")
60-
export
61-
createexperiment,
62-
getexperiment,
63-
getorcreateexperiment,
64-
deleteexperiment,
65-
restoreexperiment,
66-
searchexperiments
67-
68-
include("runs.jl")
69-
export
70-
createrun,
71-
getrun,
72-
updaterun,
73-
deleterun,
74-
searchruns
75-
76-
include("loggers.jl")
77-
export
78-
logbatch,
79-
logparam,
80-
logmetric,
81-
logartifact,
82-
listartifacts,
83-
settag
34+
include("api.jl")
8435

85-
include("deprecated.jl")
36+
include("services/experiment.jl")
8637

8738
end

src/services/experiment.jl

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
"""
2+
createexperiment(instance::MLFlow; name=missing, artifact_location=missing,
3+
tags=[])
4+
5+
Create an experiment with a name. Returns the newly created experiment.
6+
Validates that another experiment with the same name does not already exist and
7+
fails if another experiment with the same name already exists.
8+
9+
# Arguments
10+
- `instance`: [`MLFlow`](@ref) configuration.
11+
- `name::String`: Experiment name. This field is required.
12+
- `artifact_location::String`: Location where all artifacts for the experiment
13+
are stored. If not provided, the remote server will select an appropriate
14+
default.
15+
- `tags`: A collection of tags to set on the experiment.
16+
17+
# Returns
18+
An object of type [`Experiment`](@ref).
19+
"""
20+
function createexperiment(instance::MLFlow; name::String=missing,
21+
artifact_location::String=missing, tags::Array{Dict{Any, Any}}=[])
22+
if ismissing(name)
23+
name = string(UUIDs.uuid4())
24+
end
25+
26+
try
27+
result = mlfpost(instance, "experiments/create"; name=name,
28+
artifact_location=artifact_location, tags=tags)
29+
return getexperiment(instance, result["experiment_id"])
30+
catch e
31+
if isa(e, HTTP.ExceptionRequest.StatusError) && e.status == 400
32+
error_code = JSON.parse(String(e.response.body))["error_code"]
33+
if error_code == MLFLOW_ERROR_CODES.RESOURCE_ALREADY_EXISTS
34+
error("Experiment with name \"$name\" already exists")
35+
end
36+
end
37+
throw(e)
38+
end
39+
end
40+
createexperiment(instance::MLFlow; name::String=missing,
41+
artifact_location::String=missing, tags::Array{Pair{Any, Any}}=[]) =
42+
createexperiment(instance, name=name, artifact_location=artifact_location,
43+
tags=tags |> transform_pair_array_to_dict_array)
44+
createexperiment(instance::MLFlow; name::String=missing,
45+
artifact_location::String=missing, tags::Dict{Any, Any}=[]) =
46+
createexperiment(instance, name=name, artifact_location=artifact_location,
47+
tags=tags |> transform_dict_to_dict_array)
48+
createexperiment(instance::MLFlow; name::String=missing,
49+
artifact_location::String=missing, tags::Array{Tag}=[]) =
50+
createexperiment(instance, name=name, artifact_location=artifact_location,
51+
tags=tags |> transform_tag_array_to_dict_array)
52+
53+
"""
54+
getexperiment(instance::MLFlow, experiment_id::String)
55+
56+
Get metadata for an experiment. This method works on deleted experiments.
57+
58+
# Arguments
59+
- `instance`: [`MLFlow`](@ref) configuration.
60+
- `experiment_id`: ID of the associated experiment.
61+
62+
# Returns
63+
An object of type [`Experiment`](@ref).
64+
"""
65+
function getexperiment(instance::MLFlow, experiment_id::String)
66+
try
67+
arguments = (:experiment_id => experiment_id,)
68+
result = mlfget(instance, "experiments/get"; arguments...)
69+
return Experiment(result["experiment"])
70+
catch e
71+
if isa(e, HTTP.ExceptionRequest.StatusError) && e.status == 404
72+
return missing
73+
end
74+
throw(e)
75+
end
76+
end
77+
getexperiment(instance::MLFlow, experiment_id::Integer) =
78+
getexperiment(instance, experiment_id)

src/utils.jl

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,68 @@ const MLFLOW_ERROR_CODES = (;
6868
RESOURCE_ALREADY_EXISTS = "RESOURCE_ALREADY_EXISTS",
6969
RESOURCE_DOES_NOT_EXIST = "RESOURCE_DOES_NOT_EXIST",
7070
)
71+
72+
"""
73+
transform_pair_array_to_dict_array(pair_array::Array{Pair{Any, Any}})
74+
75+
Transforms an array of `Pair` into an array of `Dict`.
76+
77+
```@example
78+
# Having an array of pairs
79+
["foo" => "bar", "missy" => "gala"]
80+
81+
# Will be transformed into an array of dictionaries
82+
[Dict("key" => "foo", "value" => "bar"), Dict("key" => "missy", "value" => "gala")]
83+
```
84+
"""
85+
function transform_pair_array_to_dict_array(pair_array::Array{Pair{Any, Any}})
86+
dict_array = Dict{String, String}[]
87+
for pair in pair_array
88+
key = string(pair.first)
89+
value = string(pair.second)
90+
push!(dict_array, Dict(key => value))
91+
end
92+
return dict_array
93+
end
94+
95+
"""
96+
transform_dict_to_dict_array(dict::Dict{Any, Any})
97+
98+
Transforms a dictionary into an array of `Dict`.
99+
100+
```@example
101+
# Having a dictionary
102+
Dict("foo" => "bar", "missy" => "gala")
103+
104+
# Will be transformed into an array of dictionaries
105+
[Dict("key" => "foo", "value" => "bar"), Dict("key" => "missy", "value" => "gala")]
106+
```
107+
"""
108+
function transform_dict_to_dict_array(dict::Dict{Any, Any})
109+
dict_array = Dict{String, String}[]
110+
for (key, value) in dict
111+
push!(dict_array, Dict(string(key) => string(value)))
112+
end
113+
return dict_array
114+
end
115+
116+
"""
117+
transform_tag_array_to_dict_array(tag_array::Array{Tag})
118+
119+
Transforms an array of `Tag` into an array of `Dict`.
120+
121+
```@example
122+
# Having an array of tags
123+
[Tag("foo", "bar"), Tag("missy", "gala")]
124+
125+
# Will be transformed into an array of dictionaries
126+
[Dict("key" => "foo", "value" => "bar"), Dict("key" => "missy", "value" => "gala")]
127+
```
128+
"""
129+
function transform_tag_array_to_dict_array(tag_array::Array{Tag})
130+
dict_array = Dict{String, String}[]
131+
for tag in tag_array
132+
push!(dict_array, Dict(tag.key => tag.value))
133+
end
134+
return dict_array
135+
end

0 commit comments

Comments
 (0)