mirror of
https://github.com/wassname/optuna-dashboard.git
synced 2026-09-11 12:30:25 +08:00
Impl abstract class APIClient
This commit is contained in:
+126
-367
@@ -1,5 +1,4 @@
|
||||
import * as Optuna from "@optuna/types"
|
||||
import axios from "axios"
|
||||
import * as plotly from "plotly.js-dist-min"
|
||||
import {
|
||||
Artifact,
|
||||
@@ -17,19 +16,11 @@ import {
|
||||
TrialParam,
|
||||
} from "./types/optuna"
|
||||
|
||||
const axiosInstance = axios.create({ baseURL: API_ENDPOINT })
|
||||
|
||||
type APIMeta = {
|
||||
export type APIMeta = {
|
||||
artifact_is_available: boolean
|
||||
plotlypy_is_available: boolean
|
||||
}
|
||||
|
||||
export const getMetaInfoAPI = (): Promise<APIMeta> => {
|
||||
return axiosInstance
|
||||
.get<APIMeta>(`/api/meta`)
|
||||
.then<APIMeta>((res) => res.data)
|
||||
}
|
||||
|
||||
interface TrialResponse {
|
||||
trial_id: number
|
||||
study_id: number
|
||||
@@ -50,29 +41,6 @@ interface TrialResponse {
|
||||
constraints: number[]
|
||||
}
|
||||
|
||||
const convertTrialResponse = (res: TrialResponse): Trial => {
|
||||
return {
|
||||
trial_id: res.trial_id,
|
||||
study_id: res.study_id,
|
||||
number: res.number,
|
||||
state: res.state,
|
||||
values: res.values,
|
||||
intermediate_values: res.intermediate_values,
|
||||
datetime_start: res.datetime_start
|
||||
? new Date(res.datetime_start)
|
||||
: undefined,
|
||||
datetime_complete: res.datetime_complete
|
||||
? new Date(res.datetime_complete)
|
||||
: undefined,
|
||||
params: res.params,
|
||||
fixed_params: res.fixed_params,
|
||||
user_attrs: res.user_attrs,
|
||||
note: res.note,
|
||||
artifacts: res.artifacts,
|
||||
constraints: res.constraints,
|
||||
}
|
||||
}
|
||||
|
||||
interface PreferenceHistoryResponse {
|
||||
history: {
|
||||
id: string
|
||||
@@ -85,21 +53,7 @@ interface PreferenceHistoryResponse {
|
||||
is_removed: boolean
|
||||
}
|
||||
|
||||
const convertPreferenceHistory = (
|
||||
res: PreferenceHistoryResponse
|
||||
): PreferenceHistory => {
|
||||
return {
|
||||
id: res.history.id,
|
||||
candidates: res.history.candidates,
|
||||
clicked: res.history.clicked,
|
||||
feedback_mode: res.history.mode,
|
||||
timestamp: new Date(res.history.timestamp),
|
||||
preferences: res.history.preferences,
|
||||
is_removed: res.is_removed,
|
||||
}
|
||||
}
|
||||
|
||||
interface StudyDetailResponse {
|
||||
export interface StudyDetailResponse {
|
||||
name: string
|
||||
datetime_start: string
|
||||
directions: Optuna.StudyDirection[]
|
||||
@@ -122,52 +76,7 @@ interface StudyDetailResponse {
|
||||
skipped_trial_numbers?: number[]
|
||||
}
|
||||
|
||||
export const getStudyDetailAPI = (
|
||||
studyId: number,
|
||||
nLocalTrials: number
|
||||
): Promise<StudyDetail> => {
|
||||
return axiosInstance
|
||||
.get<StudyDetailResponse>(`/api/studies/${studyId}`, {
|
||||
params: {
|
||||
after: nLocalTrials,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
const trials = res.data.trials.map((trial): Trial => {
|
||||
return convertTrialResponse(trial)
|
||||
})
|
||||
const best_trials = res.data.best_trials.map((trial): Trial => {
|
||||
return convertTrialResponse(trial)
|
||||
})
|
||||
return {
|
||||
id: studyId,
|
||||
name: res.data.name,
|
||||
datetime_start: new Date(res.data.datetime_start),
|
||||
directions: res.data.directions,
|
||||
user_attrs: res.data.user_attrs,
|
||||
trials: trials,
|
||||
best_trials: best_trials,
|
||||
union_search_space: res.data.union_search_space,
|
||||
intersection_search_space: res.data.intersection_search_space,
|
||||
union_user_attrs: res.data.union_user_attrs,
|
||||
has_intermediate_values: res.data.has_intermediate_values,
|
||||
note: res.data.note,
|
||||
objective_names: res.data.objective_names,
|
||||
form_widgets: res.data.form_widgets,
|
||||
is_preferential: res.data.is_preferential,
|
||||
feedback_component_type: res.data.feedback_component_type,
|
||||
preferences: res.data.preferences,
|
||||
preference_history: res.data.preference_history?.map(
|
||||
convertPreferenceHistory
|
||||
),
|
||||
plotly_graph_objects: res.data.plotly_graph_objects,
|
||||
artifacts: res.data.artifacts,
|
||||
skipped_trial_numbers: res.data.skipped_trial_numbers ?? [],
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
interface StudySummariesResponse {
|
||||
export interface StudySummariesResponse {
|
||||
study_summaries: {
|
||||
study_id: number
|
||||
study_name: string
|
||||
@@ -178,26 +87,7 @@ interface StudySummariesResponse {
|
||||
}[]
|
||||
}
|
||||
|
||||
export const getStudySummariesAPI = (): Promise<StudySummary[]> => {
|
||||
return axiosInstance
|
||||
.get<StudySummariesResponse>(`/api/studies`, {})
|
||||
.then((res) => {
|
||||
return res.data.study_summaries.map((study): StudySummary => {
|
||||
return {
|
||||
study_id: study.study_id,
|
||||
study_name: study.study_name,
|
||||
directions: study.directions,
|
||||
user_attrs: study.user_attrs,
|
||||
is_preferential: study.is_preferential,
|
||||
datetime_start: study.datetime_start
|
||||
? new Date(study.datetime_start)
|
||||
: undefined,
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
interface CreateNewStudyResponse {
|
||||
export interface CreateNewStudyResponse {
|
||||
study_summary: {
|
||||
study_id: number
|
||||
study_name: string
|
||||
@@ -208,38 +98,7 @@ interface CreateNewStudyResponse {
|
||||
}
|
||||
}
|
||||
|
||||
export const createNewStudyAPI = (
|
||||
studyName: string,
|
||||
directions: Optuna.StudyDirection[]
|
||||
): Promise<StudySummary> => {
|
||||
return axiosInstance
|
||||
.post<CreateNewStudyResponse>(`/api/studies`, {
|
||||
study_name: studyName,
|
||||
directions,
|
||||
})
|
||||
.then((res) => {
|
||||
const study_summary = res.data.study_summary
|
||||
return {
|
||||
study_id: study_summary.study_id,
|
||||
study_name: study_summary.study_name,
|
||||
directions: study_summary.directions,
|
||||
// best_trial: undefined,
|
||||
user_attrs: study_summary.user_attrs,
|
||||
is_preferential: study_summary.is_preferential,
|
||||
datetime_start: study_summary.datetime_start
|
||||
? new Date(study_summary.datetime_start)
|
||||
: undefined,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteStudyAPI = (studyId: number): Promise<void> => {
|
||||
return axiosInstance.delete(`/api/studies/${studyId}`).then(() => {
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
type RenameStudyResponse = {
|
||||
export type RenameStudyResponse = {
|
||||
study_id: number
|
||||
study_name: string
|
||||
directions: Optuna.StudyDirection[]
|
||||
@@ -248,220 +107,20 @@ type RenameStudyResponse = {
|
||||
datetime_start?: string
|
||||
}
|
||||
|
||||
export const renameStudyAPI = (
|
||||
studyId: number,
|
||||
studyName: string
|
||||
): Promise<StudySummary> => {
|
||||
return axiosInstance
|
||||
.post<RenameStudyResponse>(`/api/studies/${studyId}/rename`, {
|
||||
study_name: studyName,
|
||||
})
|
||||
.then((res) => {
|
||||
return {
|
||||
study_id: res.data.study_id,
|
||||
study_name: res.data.study_name,
|
||||
directions: res.data.directions,
|
||||
user_attrs: res.data.user_attrs,
|
||||
is_preferential: res.data.is_prefential,
|
||||
datetime_start: res.data.datetime_start
|
||||
? new Date(res.data.datetime_start)
|
||||
: undefined,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const saveStudyNoteAPI = (
|
||||
studyId: number,
|
||||
note: { version: number; body: string }
|
||||
): Promise<void> => {
|
||||
return axiosInstance
|
||||
.put<void>(`/api/studies/${studyId}/note`, note)
|
||||
.then(() => {
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
export const saveTrialNoteAPI = (
|
||||
studyId: number,
|
||||
trialId: number,
|
||||
note: { version: number; body: string }
|
||||
): Promise<void> => {
|
||||
return axiosInstance
|
||||
.put<void>(`/api/studies/${studyId}/${trialId}/note`, note)
|
||||
.then(() => {
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
type UploadArtifactAPIResponse = {
|
||||
export type UploadArtifactAPIResponse = {
|
||||
artifact_id: string
|
||||
artifacts: Artifact[]
|
||||
}
|
||||
|
||||
export const uploadTrialArtifactAPI = (
|
||||
studyId: number,
|
||||
trialId: number,
|
||||
fileName: string,
|
||||
dataUrl: string
|
||||
): Promise<UploadArtifactAPIResponse> => {
|
||||
return axiosInstance
|
||||
.post<UploadArtifactAPIResponse>(`/api/artifacts/${studyId}/${trialId}`, {
|
||||
file: dataUrl,
|
||||
filename: fileName,
|
||||
})
|
||||
.then((res) => {
|
||||
return res.data
|
||||
})
|
||||
}
|
||||
|
||||
export const uploadStudyArtifactAPI = (
|
||||
studyId: number,
|
||||
fileName: string,
|
||||
dataUrl: string
|
||||
): Promise<UploadArtifactAPIResponse> => {
|
||||
return axiosInstance
|
||||
.post<UploadArtifactAPIResponse>(`/api/artifacts/${studyId}`, {
|
||||
file: dataUrl,
|
||||
filename: fileName,
|
||||
})
|
||||
.then((res) => {
|
||||
return res.data
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteTrialArtifactAPI = (
|
||||
studyId: number,
|
||||
trialId: number,
|
||||
artifactId: string
|
||||
): Promise<void> => {
|
||||
return axiosInstance
|
||||
.delete<void>(`/api/artifacts/${studyId}/${trialId}/${artifactId}`)
|
||||
.then(() => {
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteStudyArtifactAPI = (
|
||||
studyId: number,
|
||||
artifactId: string
|
||||
): Promise<void> => {
|
||||
return axiosInstance
|
||||
.delete<void>(`/api/artifacts/${studyId}/${artifactId}`)
|
||||
.then(() => {
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
export const tellTrialAPI = (
|
||||
trialId: number,
|
||||
state: Optuna.TrialStateFinished,
|
||||
values?: number[]
|
||||
): Promise<void> => {
|
||||
const req: { state: Optuna.TrialState; values?: number[] } = {
|
||||
state: state,
|
||||
values: values,
|
||||
}
|
||||
|
||||
return axiosInstance
|
||||
.post<void>(`/api/trials/${trialId}/tell`, req)
|
||||
.then(() => {
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
export const saveTrialUserAttrsAPI = (
|
||||
trialId: number,
|
||||
user_attrs: { [key: string]: number | string }
|
||||
): Promise<void> => {
|
||||
const req = { user_attrs: user_attrs }
|
||||
|
||||
return axiosInstance
|
||||
.post<void>(`/api/trials/${trialId}/user-attrs`, req)
|
||||
.then(() => {
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
interface ParamImportancesResponse {
|
||||
export interface ParamImportancesResponse {
|
||||
param_importances: ParamImportance[][]
|
||||
}
|
||||
|
||||
export const getParamImportances = (
|
||||
studyId: number
|
||||
): Promise<ParamImportance[][]> => {
|
||||
return axiosInstance
|
||||
.get<ParamImportancesResponse>(`/api/studies/${studyId}/param_importances`)
|
||||
.then((res) => {
|
||||
return res.data.param_importances
|
||||
})
|
||||
}
|
||||
|
||||
export const reportPreferenceAPI = (
|
||||
studyId: number,
|
||||
candidates: number[],
|
||||
clicked: number
|
||||
): Promise<void> => {
|
||||
return axiosInstance
|
||||
.post<void>(`/api/studies/${studyId}/preference`, {
|
||||
candidates: candidates,
|
||||
clicked: clicked,
|
||||
mode: "ChooseWorst",
|
||||
})
|
||||
.then(() => {
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
export const skipPreferentialTrialAPI = (
|
||||
studyId: number,
|
||||
trialId: number
|
||||
): Promise<void> => {
|
||||
return axiosInstance
|
||||
.post<void>(`/api/studies/${studyId}/${trialId}/skip`)
|
||||
.then(() => {
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
export const removePreferentialHistoryAPI = (
|
||||
studyId: number,
|
||||
historyUuid: string
|
||||
): Promise<void> => {
|
||||
return axiosInstance
|
||||
.delete<void>(`/api/studies/${studyId}/preference/${historyUuid}`)
|
||||
.then(() => {
|
||||
return
|
||||
})
|
||||
}
|
||||
export const restorePreferentialHistoryAPI = (
|
||||
studyId: number,
|
||||
historyUuid: string
|
||||
): Promise<void> => {
|
||||
return axiosInstance
|
||||
.post<void>(`/api/studies/${studyId}/preference/${historyUuid}`)
|
||||
.then(() => {
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
export const reportFeedbackComponentAPI = (
|
||||
studyId: number,
|
||||
component_type: FeedbackComponentType
|
||||
): Promise<void> => {
|
||||
return axiosInstance
|
||||
.put<void>(
|
||||
`/api/studies/${studyId}/preference_feedback_component`,
|
||||
component_type
|
||||
)
|
||||
.then(() => {
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
type PlotResponse = {
|
||||
export type PlotResponse = {
|
||||
data: plotly.Data[]
|
||||
layout: plotly.Layout
|
||||
}
|
||||
|
||||
export enum PlotType {
|
||||
Contour = "contour",
|
||||
Slice = "slice",
|
||||
@@ -472,25 +131,125 @@ export enum PlotType {
|
||||
ParamImportances = "param_importances",
|
||||
ParetoFront = "pareto_front",
|
||||
}
|
||||
export const getPlotAPI = (
|
||||
studyId: number,
|
||||
plotType: PlotType
|
||||
): Promise<PlotResponse> => {
|
||||
return axiosInstance
|
||||
.get<PlotResponse>(`/api/studies/${studyId}/plot/${plotType}`)
|
||||
.then<PlotResponse>((res) => res.data)
|
||||
}
|
||||
|
||||
export enum CompareStudiesPlotType {
|
||||
EDF = "edf",
|
||||
}
|
||||
export const getCompareStudiesPlotAPI = (
|
||||
studyIds: number[],
|
||||
plotType: CompareStudiesPlotType
|
||||
): Promise<PlotResponse> => {
|
||||
return axiosInstance
|
||||
.get<PlotResponse>(`/api/compare-studies/plot/${plotType}`, {
|
||||
params: { study_ids: studyIds },
|
||||
})
|
||||
.then<PlotResponse>((res) => res.data)
|
||||
|
||||
export abstract class APIClient {
|
||||
constructor() {}
|
||||
|
||||
convertTrialResponse(response: TrialResponse): Trial {
|
||||
return {
|
||||
trial_id: response.trial_id,
|
||||
study_id: response.study_id,
|
||||
number: response.number,
|
||||
state: response.state,
|
||||
values: response.values,
|
||||
intermediate_values: response.intermediate_values,
|
||||
datetime_start: response.datetime_start
|
||||
? new Date(response.datetime_start)
|
||||
: undefined,
|
||||
datetime_complete: response.datetime_complete
|
||||
? new Date(response.datetime_complete)
|
||||
: undefined,
|
||||
params: response.params,
|
||||
fixed_params: response.fixed_params,
|
||||
user_attrs: response.user_attrs,
|
||||
note: response.note,
|
||||
artifacts: response.artifacts,
|
||||
constraints: response.constraints,
|
||||
}
|
||||
}
|
||||
convertPreferenceHistory(
|
||||
response: PreferenceHistoryResponse
|
||||
): PreferenceHistory {
|
||||
return {
|
||||
id: response.history.id,
|
||||
candidates: response.history.candidates,
|
||||
clicked: response.history.clicked,
|
||||
feedback_mode: response.history.mode,
|
||||
timestamp: new Date(response.history.timestamp),
|
||||
preferences: response.history.preferences,
|
||||
is_removed: response.is_removed,
|
||||
}
|
||||
}
|
||||
|
||||
abstract getMetaInfo(): Promise<APIMeta>
|
||||
abstract getStudyDetail(
|
||||
studyId: number,
|
||||
nLocalTrials: number
|
||||
): Promise<StudyDetail>
|
||||
abstract getStudySummaries(): Promise<StudySummary[]>
|
||||
abstract createNewStudy(
|
||||
studyName: string,
|
||||
directions: Optuna.StudyDirection[]
|
||||
): Promise<StudySummary>
|
||||
abstract deleteStudy(studyId: number): Promise<void>
|
||||
abstract renameStudy(
|
||||
studyId: number,
|
||||
studyName: string
|
||||
): Promise<StudySummary>
|
||||
abstract saveStudyNote(studyId: number, note: Note): Promise<void>
|
||||
abstract saveTrialNote(
|
||||
studyId: number,
|
||||
trialId: number,
|
||||
note: Note
|
||||
): Promise<void>
|
||||
abstract uploadTrialArtifact(
|
||||
studyId: number,
|
||||
trialId: number,
|
||||
fileName: string,
|
||||
dataUrl: string
|
||||
): Promise<UploadArtifactAPIResponse>
|
||||
abstract uploadStudyArtifact(
|
||||
studyId: number,
|
||||
fileName: string,
|
||||
dataUrl: string
|
||||
): Promise<UploadArtifactAPIResponse>
|
||||
abstract deleteTrialArtifact(
|
||||
studyId: number,
|
||||
trialId: number,
|
||||
artifactId: string
|
||||
): Promise<void>
|
||||
abstract deleteStudyArtifact(
|
||||
studyId: number,
|
||||
artifactId: string
|
||||
): Promise<void>
|
||||
abstract tellTrial(
|
||||
trialId: number,
|
||||
state: Optuna.TrialStateFinished,
|
||||
values?: number[]
|
||||
): Promise<void>
|
||||
abstract saveTrialUserAttrs(
|
||||
trialId: number,
|
||||
user_attrs: { [key: string]: number | string }
|
||||
): Promise<void>
|
||||
abstract getParamImportances(studyId: number): Promise<ParamImportance[][]>
|
||||
abstract reportPreference(
|
||||
studyId: number,
|
||||
candidates: number[],
|
||||
clicked: number
|
||||
): Promise<void>
|
||||
abstract skipPreferentialTrial(
|
||||
studyId: number,
|
||||
trialId: number
|
||||
): Promise<void>
|
||||
abstract removePreferentialHistory(
|
||||
studyId: number,
|
||||
historyUuid: string
|
||||
): Promise<void>
|
||||
abstract restorePreferentialHistory(
|
||||
studyId: number,
|
||||
historyUuid: string
|
||||
): Promise<void>
|
||||
abstract reportFeedbackComponent(
|
||||
studyId: number,
|
||||
component_type: FeedbackComponentType
|
||||
): Promise<void>
|
||||
abstract getPlot(studyId: number, plotType: PlotType): Promise<PlotResponse>
|
||||
abstract getCompareStudiesPlot(
|
||||
studyIds: number[],
|
||||
plotType: CompareStudiesPlotType
|
||||
): Promise<PlotResponse>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user