kodadot/nft-gallery

View on GitHub
services/replicate.ts

Summary

Maintainability
A
3 hrs
Test Coverage
import type { FetchError } from 'ofetch'
import { $fetch } from 'ofetch'
import { URLS } from '../utils/constants'
// import consola from 'consola'

const REPLICATE_BASE_URL = URLS.koda.replicate
const VERSION
  = '42a996d39a96aedc57b2e0aa8105dea39c9c89d9d266caf6bb4327a1c191b061'
export const OUTPUTS = 4
const NEGATIVE_PROMPT
  = 'lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry, artist name'

type Option<T> = T | null

const api = $fetch.create({
  baseURL: REPLICATE_BASE_URL,
})

export type PinningKey = {
  expiry: string
  token: string
}

export type PredictionRequestStatus = {
  created_at: string
  id: string
  input: Input
  logs: Option<string>
  status: string
  version: string
}

export type PredictionRequest = {
  version: string
  input: Input
}

export type PredictionStatus = {
  completed_at: string
  created_at: string
  id: string
  input: Input
  logs: string
  // metrics: string, ?? { "predict_time": 8.760063 }
  output: Array<string>
  started_at: string
  status: string
  // urls: string, ?? { "get": "https://api.replicate.com/v1/predictions/6wkgvnkv2rhrtcjuq722vfp6mq", "cancel": "https://api.replicate.com/v1/predictions/6wkgvnkv2rhrtcjuq722vfp6mq/cancel" }
  version: string
}

export type Input = {
  prompt: string
  negative_prompt?: string
  width: Option<number>
  height: Option<number>
  num_outputs: Option<number>
  guidance_scale: Option<number>
  num_inference_steps: Option<number>
}

export const predict = async (
  object: string,
): Promise<PredictionRequestStatus> => {
  const input: PredictionRequest = {
    version: VERSION,
    input: {
      prompt: object,
      negative_prompt: NEGATIVE_PROMPT,
      width: 512,
      height: 512,
      num_outputs: OUTPUTS,
      guidance_scale: 7,
      num_inference_steps: 50,
    },
  }
  const value = await api<PredictionRequestStatus>('predict', {
    method: 'POST',
    body: input,
  }).catch((error: FetchError) => {
    throw new Error(
      `[REPLICATE::PREDICT] Unable to PREDICT for reasons ${error.data}`,
    )
  })
  return value
}

export const getPrediction = async (
  predictionId: string,
): Promise<PredictionStatus> => {
  const prediction = await api<PredictionStatus>(
    `status/${predictionId}`,
  ).catch((error: FetchError) => {
    throw new Error(
      `[REPLICATE::STATUS] Unable to GET STATUS for reasons ${error.data}`,
    )
  })
  return prediction
}

export default api