import {z} from 'zod' export type GetApiApiProjectIdOptimizeStateArgs = {projectId: number}; export type GetApiApiProjectIdOptimizeStateOptions = {baseUrl?: string | undefined, ApiKeyAuthentication?: string | undefined, fetch?: typeof fetch | undefined}; export const tunerSpaceInputBlock = z.record(z.string(), z.unknown()); export const tunerSpaceDSPBlock = z.record(z.string(), z.unknown()); export const tunerSpaceLearnBlock = z.record(z.string(), z.unknown()); export const tunerSpaceImpulse = z.object({parameters: z.object({}).optional(), inputBlocks: z.array(tunerSpaceInputBlock), dspBlocks: z.array(tunerSpaceDSPBlock), learnBlocks: z.array(z.array(tunerSpaceLearnBlock))}); export const optimizeConfig = z.object({name: z.string().optional(), targetLatency: z.number().int(), targetDevice: z.object({name: z.string(), ram: z.number().int().optional(), rom: z.number().int().optional()}), compiler: z.array(z.string()).optional(), precision: z.array(z.string()).optional(), trainingCycles: z.number().int().optional(), tuningMaxTrials: z.number().int().optional(), tuningWorkers: z.number().int().optional(), initialTrials: z.number().int().optional(), optimizationRounds: z.number().int().optional(), trialsPerOptimizationRound: z.number().int().optional(), minMACCS: z.number().optional(), maxMACCS: z.number().optional(), tuningAlgorithm: z.enum(["random", "hyperband", "bayesian", "custom"]).optional(), notificationOnCompletion: z.boolean().optional(), importProjectMetrics: z.boolean().optional(), importResourceMetrics: z.boolean().optional(), numImportProjectMetrics: z.number().optional(), numImportResourceMetrics: z.number().optional(), enableSEM: z.boolean().optional(), accuracySEM: z.number().optional(), latencySEM: z.number().optional(), optimizationObjectives: z.array(z.object({objective: z.string(), label: z.string(), weight: z.number()})).optional(), rawObjectives: z.string().optional(), optimizationPrecision: z.enum(["float32", "int8"]).optional(), earlyStopping: z.boolean().optional(), earlyStoppingWindowSize: z.number().optional(), earlyStoppingImprovementBar: z.number().optional(), MOMF: z.boolean().optional(), verboseLogging: z.boolean().optional(), disableConstraints: z.boolean().optional(), disableDeduplicate: z.boolean().optional(), maxTotalTrainingTime: z.number().optional(), tunerChildJobMemoryMiB: z.number().int().gte(1).lte(65536).optional(), tunerSpaceOptions: z.record(z.string(), z.array(z.string())).optional(), space: z.array(tunerSpaceImpulse).optional(), searchSpaceTemplate: z.object({identifier: z.enum(["speech_keyword", "speech_continuous", "audio_event", "audio_continuous", "visual", "motion_event", "motion_continuous", "audio_syntiant", "object_detection_bounding_boxes", "object_detection_centroids", "visual_ad", "object_detection_yolo_pro"]), classification: z.boolean().optional(), anomaly: z.boolean().optional(), regression: z.boolean().optional()}).optional(), searchSpaceSource: z.object({type: z.enum(["template", "run", "impulse", "custom"]), templateTitle: z.string().optional(), runTitle: z.string().optional(), impulseTitle: z.string().optional()}).optional()}); export const tunerCreateTrialInputBlock = z.record(z.string(), z.unknown()); export const tunerCreateTrialDSPBlock = z.record(z.string(), z.unknown()); export const tunerCreateTrialLearnBlock = z.record(z.string(), z.unknown()); export const tunerTrialImpulse = z.object({inputBlocks: z.array(tunerCreateTrialInputBlock).optional(), dspBlocks: z.array(tunerCreateTrialDSPBlock).optional(), learnBlocks: z.array(tunerCreateTrialLearnBlock).optional()}); export const kerasModelTypeEnum = z.enum(["int8", "float32", "akida", "requiresRetrain"]); export const kerasCustomMetric = z.object({name: z.string(), value: z.string()}); export const boundingBoxWithScore = z.object({label: z.string(), x: z.number(), y: z.number(), width: z.number(), height: z.number(), score: z.number()}); export const modelPrediction = z.object({sampleId: z.number().int(), startMs: z.number(), endMs: z.number(), label: z.string().optional(), prediction: z.string(), predictionCorrect: z.boolean().optional(), expectedAnomalyOutcome: z.string().optional(), f1Score: z.number().optional(), anomalyScores: z.array(z.array(z.number())).optional(), boundingBoxes: z.array(boundingBoxWithScore).optional(), labelMapPredictions: z.record(z.string(), z.string()).optional()}); export const additionalMetric = z.object({name: z.string(), value: z.string(), fullPrecisionValue: z.number(), tooltipText: z.string().optional(), link: z.string().optional()}); export const kerasModelMetadataMetrics = z.object({type: kerasModelTypeEnum, loss: z.number(), accuracy: z.number().optional(), confusionMatrix: z.array(z.array(z.number())), report: z.object({}), onDevicePerformance: z.array(z.object({mcu: z.string(), name: z.string(), isDefault: z.boolean(), latency: z.number(), tflite: z.object({ramRequired: z.number().int(), romRequired: z.number().int(), arenaSize: z.number().int(), modelSize: z.number().int()}), eon: z.object({ramRequired: z.number().int(), romRequired: z.number().int(), arenaSize: z.number().int(), modelSize: z.number().int()}), eon_ram_optimized: z.object({ramRequired: z.number().int(), romRequired: z.number().int(), arenaSize: z.number().int(), modelSize: z.number().int()}).optional(), customMetrics: z.array(kerasCustomMetric).optional(), hasPerformance: z.boolean(), profilingError: z.string().optional()})), predictions: z.array(modelPrediction).optional(), visualization: z.enum(["featureExplorer", "dataExplorer", "none"]), isSupportedOnMcu: z.boolean(), mcuSupportError: z.string().optional(), profilingJobId: z.number().int().optional(), profilingJobFailed: z.boolean().optional(), additionalMetrics: z.array(additionalMetric)}); export const tunerTrial = z.object({id: z.string(), name: z.string(), status: z.enum(["pending", "running", "completed", "failed"]), lastCompletedEpoch: z.string().optional(), lastCompletedTraining: z.string().optional(), retries: z.number().int().optional(), currentEpoch: z.number().int().optional(), workerId: z.string().optional(), blocks: z.array(z.object({id: z.number().int(), lastActive: z.string().optional(), retries: z.number().int(), status: z.enum(["pending", "running", "completed", "failed"]), type: z.enum(["input", "dsp", "learn"]), modelBlockIndex: z.number().int().optional()})), impulse: tunerTrialImpulse, experiment: z.string().optional(), original_trial_id: z.string().optional(), model: z.record(z.string(), z.unknown()).optional(), dspJobId: z.object({training: z.number().optional(), testing: z.number().optional()}).optional(), learnJobId: z.number().optional(), devicePerformance: z.record(z.string(), z.unknown()).optional(), optimizationRound: z.number().optional(), progress: z.object({epoch: z.number(), loss: z.number(), val_loss: z.number(), accuracy: z.number(), val_accuracy: z.number()}).optional(), metrics: z.object({test: z.object({float32: kerasModelMetadataMetrics.optional(), int8: kerasModelMetadataMetrics.optional()}).optional(), train: z.object({float32: kerasModelMetadataMetrics.optional(), int8: kerasModelMetadataMetrics.optional()}).optional(), validation: z.object({float32: kerasModelMetadataMetrics.optional(), int8: kerasModelMetadataMetrics.optional()}).optional()}).optional(), impulseAddedToProject: z.object({impulseId: z.number().int(), link: z.string()}).optional(), createdInPostProcessing: z.boolean().optional()}); export const optimizeStateResponse = z.object({success: z.boolean(), error: z.string().optional(), config: optimizeConfig, status: z.object({numPendingTrials: z.number().int(), numRunningTrials: z.number().int(), numCompletedTrials: z.number().int(), numFailedTrials: z.number().int(), numReadyWorkers: z.number().int(), numBusyWorkers: z.number().int(), numPendingWorkers: z.number().int(), status: z.enum(["creating", "ready", "running", "completed"])}), tunerJobId: z.number().int().optional(), tunerCoordinatorJobId: z.number().int().optional(), continuationJobId: z.number().int().optional(), tuningAlgorithm: z.enum(["random", "hyperband", "bayesian", "custom"]).optional(), tunerJobIsRunning: z.boolean(), trials: z.array(tunerTrial), projectDataType: z.enum(["audio", "image", "motion", "other"]), jobError: z.string().optional(), workers: z.array(z.object({workerId: z.string(), status: z.enum(["pending", "ready", "busy"])})), nextRunIndex: z.number().int(), canExtendSearch: z.boolean(), isWhitelabel: z.boolean(), totalTrainingTimeExceeded: z.boolean()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Retrieves the EON tuner state * * GET /api/{projectId}/optimize/state * * Also accepts auth: JWTAuthentication, JWTHttpHeaderAuthentication, OAuth2 */ export const getApiApiProjectIdOptimizeState = async (args: GetApiApiProjectIdOptimizeStateArgs, options?: GetApiApiProjectIdOptimizeStateOptions) => { const {baseUrl = "https://studio.edgeimpulse.com/v1", fetch: fetchFn = fetch, ApiKeyAuthentication} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (ApiKeyAuthentication !== undefined) headers.set("x-api-key", ApiKeyAuthentication) const url = `${baseUrl.replace(/\/+$/, '')}/api/${encodeURIComponent(String(args.projectId))}/optimize/state${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(optimizeStateResponse, await res.json()) };