Impl abstract class APIClient

This commit is contained in:
porink0424
2024-04-24 16:54:36 +09:00
parent 480ac9ec49
commit ddeea56675
+126 -367
View File
@@ -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>
}