{"version":3,"sources":["../src/imagen.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { z, type Genkit } from 'genkit';\nimport {\n  GenerationCommonConfigSchema,\n  getBasicUsageStats,\n  modelRef,\n  type CandidateData,\n  type GenerateRequest,\n  type ModelAction,\n  type ModelInfo,\n  type ModelReference,\n} from 'genkit/model';\nimport type { GoogleAuth } from 'google-auth-library';\nimport type { PluginOptions } from './common/types.js';\nimport { predictModel, type PredictClient } from './predict.js';\n\n/**\n * See https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/imagen-api.\n * @deprecated\n */\nexport const ImagenConfigSchema = GenerationCommonConfigSchema.extend({\n  // TODO: Remove common config schema extension since Imagen models don't support\n  // most of the common config parameters. Also, add more parameters like sampleCount\n  // from the above reference.\n  language: z\n    .enum(['auto', 'en', 'es', 'hi', 'ja', 'ko', 'pt', 'zh-TW', 'zh', 'zh-CN'])\n    .describe('Language of the prompt text.')\n    .optional(),\n  aspectRatio: z\n    .enum(['1:1', '9:16', '16:9', '3:4', '4:3'])\n    .describe('Desired aspect ratio of the output image.')\n    .optional(),\n  negativePrompt: z\n    .string()\n    .describe(\n      'A description of what to discourage in the generated images. ' +\n        'For example: \"animals\" (removes animals), \"blurry\" ' +\n        '(makes the image clearer), \"text\" (removes text), or ' +\n        '\"cropped\" (removes cropped images).'\n    )\n    .optional(),\n  seed: z\n    .number()\n    .int()\n    .min(1)\n    .max(2147483647)\n    .describe(\n      'Controls the randomization of the image generation process. Use the ' +\n        'same seed across requests to provide consistency, or change it to ' +\n        'introduce variety in the response.'\n    )\n    .optional(),\n  location: z\n    .string()\n    .describe('Google Cloud region e.g. us-central1.')\n    .optional(),\n  personGeneration: z\n    .enum(['dont_allow', 'allow_adult', 'allow_all'])\n    .describe('Control if/how images of people will be generated by the model.')\n    .optional(),\n  safetySetting: z\n    .enum(['block_most', 'block_some', 'block_few', 'block_fewest'])\n    .describe('Adds a filter level to safety filtering.')\n    .optional(),\n  addWatermark: z\n    .boolean()\n    .describe('Add an invisible watermark to the generated images.')\n    .optional(),\n  storageUri: z\n    .string()\n    .describe('Cloud Storage URI to store the generated images.')\n    .optional(),\n  mode: z\n    .enum(['upscale'])\n    .describe('Mode must be set for upscaling requests.')\n    .optional(),\n  /**\n   * Describes the editing intention for the request.\n   *\n   * See https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/imagen-api#edit_images_2 for details.\n   */\n  editConfig: z\n    .object({\n      editMode: z\n        .enum([\n          'inpainting-insert',\n          'inpainting-remove',\n          'outpainting',\n          'product-image',\n        ])\n        .describe('Editing intention for the request.')\n        .optional(),\n      maskMode: z\n        .object({\n          maskType: z\n            .enum(['background', 'foreground', 'semantic'])\n            .describe(\n              '\"background\" automatically generates a mask for all ' +\n                'regions except the primary subject(s) of the image, ' +\n                '\"foreground\" automatically generates a mask for the primary ' +\n                'subjects(s) of the image. \"semantic\" segments one or more ' +\n                'of the segmentation classes using class ID.'\n            ),\n          classes: z\n            .array(z.number())\n            .describe('List of class IDs for segmentation.')\n            .length(5)\n            .optional(),\n        })\n        .describe(\n          'Prompts the model to generate a mask instead of you ' +\n            'needing to provide one. Consequently, when you provide ' +\n            'this parameter you can omit a mask object.'\n        )\n        .optional(),\n      maskDilation: z\n        .number()\n        .describe('Dilation percentage of the mask provided.')\n        .min(0.0)\n        .max(1.0)\n        .optional(),\n      guidanceScale: z\n        .number()\n        .describe(\n          'Controls how much the model adheres to the text prompt. ' +\n            'Large values increase output and prompt alignment, but may ' +\n            'compromise image quality. Suggested values are 0-9 ' +\n            '(low strength), 10-20 (medium strength), 21+ (high strength).'\n        )\n        .optional(),\n      productPosition: z\n        .enum(['reposition', 'fixed'])\n        .describe(\n          'Defines whether the product should stay fixed or be ' +\n            'repositioned.'\n        )\n        .optional(),\n    })\n    .passthrough()\n    .optional(),\n  upscaleConfig: z\n    .object({\n      upscaleFactor: z\n        .enum(['x2', 'x4'])\n        .describe('The factor to upscale the image.'),\n    })\n    .describe('Configuration for upscaling.')\n    .optional(),\n}).passthrough();\n\n/** @deprecated */\nexport const imagen2 = modelRef({\n  name: 'vertexai/imagen2',\n  info: {\n    label: 'Vertex AI - Imagen2',\n    versions: ['imagegeneration@006', 'imagegeneration@005'],\n    supports: {\n      media: false,\n      multiturn: false,\n      tools: false,\n      systemRole: false,\n      output: ['media'],\n    },\n  },\n  version: 'imagegeneration@006',\n  configSchema: ImagenConfigSchema,\n});\n\n/** @deprecated */\nexport const imagen3 = modelRef({\n  name: 'vertexai/imagen3',\n  info: {\n    label: 'Vertex AI - Imagen3',\n    versions: ['imagen-3.0-generate-001'],\n    supports: {\n      media: true,\n      multiturn: false,\n      tools: false,\n      systemRole: false,\n      output: ['media'],\n    },\n  },\n  version: 'imagen-3.0-generate-001',\n  configSchema: ImagenConfigSchema,\n});\n\n/** @deprecated */\nexport const imagen3Fast = modelRef({\n  name: 'vertexai/imagen3-fast',\n  info: {\n    label: 'Vertex AI - Imagen3 Fast',\n    versions: ['imagen-3.0-fast-generate-001'],\n    supports: {\n      media: false,\n      multiturn: false,\n      tools: false,\n      systemRole: false,\n      output: ['media'],\n    },\n  },\n  version: 'imagen-3.0-fast-generate-001',\n  configSchema: ImagenConfigSchema,\n});\n\n/** @deprecated */\nexport const ACTUAL_IMAGEN_MODELS = {\n  'imagen-3.0-generate-001': modelRef({\n    name: 'vertexai/imagen-3.0-generate-001',\n    info: {\n      label: 'Vertex AI - imagen-3.0-generate-001',\n      supports: {\n        media: true,\n        multiturn: false,\n        tools: false,\n        systemRole: false,\n        output: ['media'],\n      },\n    },\n    configSchema: ImagenConfigSchema,\n  }),\n  'imagen-3.0-fast-generate-001': modelRef({\n    name: 'vertexai/imagen-3.0-fast-generate-001',\n    info: {\n      label: 'Vertex AI - imagen-3.0-fast-generate-001',\n      supports: {\n        media: true,\n        multiturn: false,\n        tools: false,\n        systemRole: false,\n        output: ['media'],\n      },\n    },\n    configSchema: ImagenConfigSchema,\n  }),\n} as const;\n\n/** @deprecated */\nexport const SUPPORTED_IMAGEN_MODELS = {\n  ...ACTUAL_IMAGEN_MODELS,\n  // These are old, inconsistent model naming. Only here for backwards compatibility.\n  imagen2: imagen2,\n  imagen3: imagen3,\n  'imagen3-fast': imagen3Fast,\n};\n\nfunction extractText(request: GenerateRequest) {\n  return request.messages\n    .at(-1)!\n    .content.map((c) => c.text || '')\n    .join('');\n}\n\ninterface ImagenParameters {\n  sampleCount?: number;\n  aspectRatio?: string;\n  negativePrompt?: string;\n  seed?: number;\n  language?: string;\n  personGeneration?: string;\n  safetySetting?: string;\n  addWatermark?: boolean;\n  storageUri?: string;\n}\n\nfunction toParameters(\n  request: GenerateRequest<typeof ImagenConfigSchema>\n): ImagenParameters {\n  const out = {\n    sampleCount: request.candidates ?? 1,\n    ...request?.config,\n  };\n\n  for (const k in out) {\n    if (!out[k]) delete out[k];\n  }\n\n  return out;\n}\n\nfunction extractMaskImage(request: GenerateRequest): string | undefined {\n  return request.messages\n    .at(-1)\n    ?.content.find((p) => !!p.media && p.metadata?.type === 'mask')\n    ?.media?.url.split(',')[1];\n}\n\nfunction extractBaseImage(request: GenerateRequest): string | undefined {\n  return request.messages\n    .at(-1)\n    ?.content.find(\n      (p) => !!p.media && (!p.metadata?.type || p.metadata?.type === 'base')\n    )\n    ?.media?.url.split(',')[1];\n}\n\ninterface ImagenPrediction {\n  bytesBase64Encoded: string;\n  mimeType: string;\n}\n\ninterface ImagenInstance {\n  prompt: string;\n  image?: { bytesBase64Encoded: string };\n  mask?: { image?: { bytesBase64Encoded: string } };\n}\n\n/** @deprecated */\nexport const GENERIC_IMAGEN_INFO = {\n  label: `Vertex AI - Generic`,\n  supports: {\n    media: true,\n    multiturn: true,\n    tools: true,\n    systemRole: true,\n    output: ['media'],\n  },\n} as ModelInfo;\n\n/** @deprecated */\nexport function defineImagenModel(\n  ai: Genkit,\n  name: string,\n  client: GoogleAuth,\n  options: PluginOptions\n): ModelAction {\n  const modelName = `vertexai/${name}`;\n  const model: ModelReference<z.ZodTypeAny> =\n    SUPPORTED_IMAGEN_MODELS[name] ||\n    modelRef({\n      name: modelName,\n      info: {\n        ...GENERIC_IMAGEN_INFO,\n        label: `Vertex AI - ${name}`,\n      },\n      configSchema: ImagenConfigSchema,\n    });\n\n  const predictClients: Record<\n    string,\n    PredictClient<ImagenInstance, ImagenPrediction, ImagenParameters>\n  > = {};\n  const predictClientFactory = (\n    request: GenerateRequest<typeof ImagenConfigSchema>\n  ): PredictClient<ImagenInstance, ImagenPrediction, ImagenParameters> => {\n    const requestLocation = request.config?.location || options.location;\n    if (!predictClients[requestLocation]) {\n      predictClients[requestLocation] = predictModel<\n        ImagenInstance,\n        ImagenPrediction,\n        ImagenParameters\n      >(\n        client,\n        {\n          ...options,\n          location: requestLocation,\n        },\n        request.config?.version || model.version || name\n      );\n    }\n    return predictClients[requestLocation];\n  };\n\n  return ai.defineModel(\n    {\n      name: modelName,\n      ...model.info,\n      configSchema: ImagenConfigSchema,\n    },\n    async (request) => {\n      const instance: ImagenInstance = {\n        prompt: extractText(request),\n      };\n      const baseImage = extractBaseImage(request);\n      if (baseImage) {\n        instance.image = { bytesBase64Encoded: baseImage };\n      }\n      const maskImage = extractMaskImage(request);\n      if (maskImage) {\n        instance.mask = {\n          image: { bytesBase64Encoded: maskImage },\n        };\n      }\n\n      const predictClient = predictClientFactory(request);\n      const response = await predictClient([instance], toParameters(request));\n\n      if (!response.predictions || response.predictions.length == 0) {\n        throw new Error(\n          'Model returned no predictions. Possibly due to content filters.'\n        );\n      }\n\n      const candidates: CandidateData[] = response.predictions.map((p, i) => {\n        const b64data = p.bytesBase64Encoded;\n        const mimeType = p.mimeType;\n        return {\n          index: i,\n          finishReason: 'stop',\n          message: {\n            role: 'model',\n            content: [\n              {\n                media: {\n                  url: `data:${mimeType};base64,${b64data}`,\n                  contentType: mimeType,\n                },\n              },\n            ],\n          },\n        };\n      });\n      return {\n        candidates,\n        usage: {\n          ...getBasicUsageStats(request.messages, candidates),\n          custom: { generations: candidates.length },\n        },\n        custom: response,\n      };\n    }\n  );\n}\n"],"mappings":"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","names":[]}