首页 >web前端 >js教程 >掌握构建器模式:创建动态 AI 提示生成器 CLI

掌握构建器模式:创建动态 AI 提示生成器 CLI

Susan Sarandon
Susan Sarandon原创
2024-11-15 05:30:031047浏览

您在开发过程中是否遇到过需要处理复杂对象的情况?可能是因为它们要么参数太多,甚至可以嵌套,要么需要很多构建步骤和复杂的逻辑来构建。

也许您想设计一个具有简洁界面的模块,而不必每次都分散或思考复杂对象的创建代码!

这就是构建器设计模式的用武之地!

在本教程中,我们将解释有关构建器设计模式的所有内容,然后我们将构建一个 CLI Node.js 应用程序,用于使用 构建器设计模式 生成 DALL-E 3 优化的图像生成提示.

最终代码可在此 Github 存储库中获取。

概述

问题

Builder 是一种 创造设计模式,它是一类设计模式,用于处理使用 new 创建对象的本机方式所带来的不同问题。 关键字或运算符。

构建器设计模式专注于解决以下问题:

  1. 提供一个简单的接口来创建复杂的对象:想象一个深度嵌套的对象,它具有许多必需的初始化步骤。

  2. 将构造代码与对象本身分开,允许从同一对象创建多个表示或配置。

解决方案

Builder 设计模式 通过将对象创建的责任委托给称为 builders 的特殊对象来解决这两个问题。

构建器对象组合原始对象,并将创建过程分解为多个阶段或步骤。

每个步骤都由构建器对象中的一个方法定义,该方法根据某些业务逻辑初始化对象属性的子集。

class PromptBuilder {
  private prompt: Prompt

  constructor() {
    this.reset()
  }

  reset() {
    this.prompt = new Prompt()
  }

  buildStep1() {
    this.prompt.subject = "A cheese eating a burger"
    //initialization code...
    return this
  }

  buildStep2() {
    //initialization code...
    return this
  }

  buildStep3() {
    //initialization code...
    return this
  }

  build() {
    const result = structuredClone(this.prompt) // deep clone
    this.reset()
    return result
  }
}

客户端代码:我们只需要使用构建器并调用各个步骤

const promptBuilder = new PromptBuilder()
const prompt1 = promptBuilder
  .buildStep1() // optional
  .buildStep2() // optional
  .buildStep3() // optional
  .build() // we've got a prompt

const prompt2 = promptBuilder
  .buildStep1() // optional
  .buildStep3() // optional
  .build() // we've got a prompt

典型的构建器设计模式

Mastering the Builder Pattern: Create a Dynamic AI Prompt Generator CLI

典型的构建器设计模式由 4 个主要类组成:

  1. Builder :构建器接口应该只定义构造方法,而没有 build() 方法,该方法负责返回创建的实体。

  2. 具体构建器类:每个具体构建器都提供自己的构建器接口方法的实现,以便它可以生成自己的对象变体(产品1产品2)。

  3. 客户端 :您可以将客户端视为我们对象的顶级消费者、导入库模块的用户或我们应用程序的入口点。

  4. Director:即使同一个构建器对象也可以产生该对象的许多变体。

class PromptBuilder {
  private prompt: Prompt

  constructor() {
    this.reset()
  }

  reset() {
    this.prompt = new Prompt()
  }

  buildStep1() {
    this.prompt.subject = "A cheese eating a burger"
    //initialization code...
    return this
  }

  buildStep2() {
    //initialization code...
    return this
  }

  buildStep3() {
    //initialization code...
    return this
  }

  build() {
    const result = structuredClone(this.prompt) // deep clone
    this.reset()
    return result
  }
}

从上面的代码中可以看出,某些实体非常需要负责指导或编排对构建器方法的不同可能的调用组合序列,因为每个序列可能会产生不同的结果对象。

那么我们能否进一步抽象流程,为客户端代码提供更简单的接口?

这就是

Director 类 的用武之地。director 从客户端承担更多责任,并允许我们分解所有这些构建器序列调用并根据需要重用它们。

const promptBuilder = new PromptBuilder()
const prompt1 = promptBuilder
  .buildStep1() // optional
  .buildStep2() // optional
  .buildStep3() // optional
  .build() // we've got a prompt

const prompt2 = promptBuilder
  .buildStep1() // optional
  .buildStep3() // optional
  .build() // we've got a prompt

客户端代码


const promptBuilder = new PromptBuilder()
const prompt1 = promptBuilder.buildStep1().buildStep2().build()

const prompt2 = promptBuilder.buildStep1().buildStep3().build()

从上面的代码可以看出,客户端代码不需要知道创建prompt1或prompt2的详细信息。它只是调用主管,设置正确的构建器对象,然后调用 makePrompt 方法。

实际场景

为了进一步展示构建器设计模式的实用性,让我们从头开始构建一个

快速工程图像生成AI CLI工具

此 CLI 应用程序的源代码可在此处获取。

CLI 工具的工作方式如下:

    CLI 将提示用户选择一种提示风格:现实或数字艺术。
  1. 然后它会要求用户输入提示主题,例如:奶酪吃汉堡。
  2. 根据您的选择(数字艺术或现实),CLI 工具将创建包含许多配置详细信息的复杂提示对象。
真实的提示需要构建以下所有配置属性。

文件:promps.ts


class Director {
  private builder: PromptBuilder
  constructor() {}

  setBuilder(builder: PromptBuilder) {
    this.builder = builder
  }

  makePrompt1() {
    return this.builder.buildStep1().buildStep2().build()
  }

  makePrompt2() {
    return this.builder.buildStep1().buildStep3().build()
  }
}

文件:promps.ts


const director = new Director()
const builder = new PromptBuilder()
director.setBuilder(builder)
const prompt1 = director.makePrompt1()
const prompt2 = director.makePrompt2()

如您所见,每种提示类型都需要构建许多复杂的属性,例如

artStylecolorPalettelightingEffectperspective , 相机类型 ,等等

随意探索所有属性详细信息,这些详细信息在我们项目的

enums.ts 文件中定义。

枚举.ts


class PromptBuilder {
  private prompt: Prompt

  constructor() {
    this.reset()
  }

  reset() {
    this.prompt = new Prompt()
  }

  buildStep1() {
    this.prompt.subject = "A cheese eating a burger"
    //initialization code...
    return this
  }

  buildStep2() {
    //initialization code...
    return this
  }

  buildStep3() {
    //initialization code...
    return this
  }

  build() {
    const result = structuredClone(this.prompt) // deep clone
    this.reset()
    return result
  }
}

我们的 CLI 应用程序的用户可能不知道所有这些配置;他们可能只想根据特定的主题生成图像,例如吃奶酪汉堡和风格(现实或数字艺术)。

克隆 Github 存储库后,使用以下命令安装依赖项:

const promptBuilder = new PromptBuilder()
const prompt1 = promptBuilder
  .buildStep1() // optional
  .buildStep2() // optional
  .buildStep3() // optional
  .build() // we've got a prompt

const prompt2 = promptBuilder
  .buildStep1() // optional
  .buildStep3() // optional
  .build() // we've got a prompt

安装依赖项后,运行以下命令:

const promptBuilder = new PromptBuilder()
const prompt1 = promptBuilder.buildStep1().buildStep2().build()

const prompt2 = promptBuilder.buildStep1().buildStep3().build()

系统将提示您选择提示类型:现实数字艺术Mastering the Builder Pattern: Create a Dynamic AI Prompt Generator CLI

然后您必须输入提示的主题。让我们坚持芝士汉堡

根据您的选择,您将收到以下文字提示:

写实风格提示 :

class Director {
  private builder: PromptBuilder
  constructor() {}

  setBuilder(builder: PromptBuilder) {
    this.builder = builder
  }

  makePrompt1() {
    return this.builder.buildStep1().buildStep2().build()
  }

  makePrompt2() {
    return this.builder.buildStep1().buildStep3().build()
  }
}

数字艺术风格提示 :

const director = new Director()
const builder = new PromptBuilder()
director.setBuilder(builder)
const prompt1 = director.makePrompt1()
const prompt2 = director.makePrompt2()

复制之前的命令,然后将其粘贴到 ChatGPT 中。 ChatGPT 将使用 DALL-E 3 模型来生成图像。

真实图像提示结果

数字艺术图像提示结果

Mastering the Builder Pattern: Create a Dynamic AI Prompt Generator CLI

Mastering the Builder Pattern: Create a Dynamic AI Prompt Generator CLI

记住提示参数的复杂性以及构建每种类型的提示所需的专业知识,更不用说所需的丑陋的构造函数调用。

class RealisticPhotoPrompt {
  constructor(
    public subject: string,
    public location: string,
    public timeOfDay: string,
    public weather: string,
    public camera: CameraType,
    public lens: LensType,
    public focalLength: number,
    public aperture: string,
    public iso: number,
    public shutterSpeed: string,
    public lighting: LightingCondition,
    public composition: CompositionRule,
    public perspective: string,
    public foregroundElements: string[],
    public backgroundElements: string[],
    public colorScheme: ColorScheme,
    public resolution: ImageResolution,
    public postProcessing: string[]
  ) {}
}

免责声明:这种丑陋的构造函数调用在 JavaScript 中并不是一个大问题,因为我们可以传递一个所有属性都可为空的配置对象。

抽象构建提示的过程,并使我们的代码开放扩展并关闭修改(O in SOLID),并让我们的图书馆客户无缝或更轻松地使用我们的提示生成库,我们将选择实施构建器设计模式

让我们首先声明通用提示生成器接口

接口声明了一堆方法:

  1. buildBasePropertiesbuildTechnicalDetailsbuildArtisticElements 是构建 RealisticDigital Art 提示的步骤。
  2. setSubject 是我们所有提示构建器之间的共享方法;它是不言自明的,将用于设置提示主题。

builders.ts

class PromptBuilder {
  private prompt: Prompt

  constructor() {
    this.reset()
  }

  reset() {
    this.prompt = new Prompt()
  }

  buildStep1() {
    this.prompt.subject = "A cheese eating a burger"
    //initialization code...
    return this
  }

  buildStep2() {
    //initialization code...
    return this
  }

  buildStep3() {
    //initialization code...
    return this
  }

  build() {
    const result = structuredClone(this.prompt) // deep clone
    this.reset()
    return result
  }
}

builders.ts

const promptBuilder = new PromptBuilder()
const prompt1 = promptBuilder
  .buildStep1() // optional
  .buildStep2() // optional
  .buildStep3() // optional
  .build() // we've got a prompt

const prompt2 = promptBuilder
  .buildStep1() // optional
  .buildStep3() // optional
  .build() // we've got a prompt

从上面的实现中可以看到,每个构建器都选择构建自己类型的提示(最终的提示形状不同),同时坚持 PromptBuilder 合约定义的相同构建步骤!

现在,让我们继续我们的 Director 类定义。

导演.ts

const promptBuilder = new PromptBuilder()
const prompt1 = promptBuilder.buildStep1().buildStep2().build()

const prompt2 = promptBuilder.buildStep1().buildStep3().build()

Director 类包装了 PromptBuilder 并允许我们创建一个提示配置,其中包括调用从 setSubject 的所有构建器方法buildArtisticElements.

这将简化 index.ts 文件中的客户端代码,我们将在下一节中看到。

序列化器.ts

class Director {
  private builder: PromptBuilder
  constructor() {}

  setBuilder(builder: PromptBuilder) {
    this.builder = builder
  }

  makePrompt1() {
    return this.builder.buildStep1().buildStep2().build()
  }

  makePrompt2() {
    return this.builder.buildStep1().buildStep3().build()
  }
}

为了将最终提示文本打印到终端控制台,我实现了一些实用程序序列化函数。

现在我们的提示库生成代码已经准备好了。让我们在 index.ts 文件中使用它。

index.ts

const director = new Director()
const builder = new PromptBuilder()
director.setBuilder(builder)
const prompt1 = director.makePrompt1()
const prompt2 = director.makePrompt2()

上面的代码执行以下操作:

  1. 使用询问器包提示用户选择提示样式和主题:getUserInput.
  2. 从用户那里获取主题和艺术风格后,客户端代码仅使用我们库中的两个组件:PromptBuilderDirector
  3. 我们首先实例化 Director
  4. 然后,根据选择的提示样式,我们实例化相应的构建器,并将其设置为Director类。
  5. 最后,我们以所选主题作为参数调用
  6. director.makePrompt 方法,从 builder 获取提示,并将序列化的提示打印到终端控制台。
请记住:不可能从导演那里获得提示,因为每种构建器类型产生的提示形状不同。

结论

Builder 设计模式被证明是创建具有多种配置的复杂对象的出色解决方案,如我们的 AI 图像提示生成 CLI 应用程序所示。这就是为什么 Builder 模式在这种情况下很有用:

  1. 简化对象创建:该模式允许我们创建复杂的 RealisticPhotoPrompt 和 DigitalArtPrompt 对象,而无需将其复杂的构造过程暴露给客户端代码。

  2. 灵活性:通过为每种提示类型使用单独的构建器类,我们可以轻松添加新的提示类型或修改现有的提示类型,而无需更改客户端代码。

  3. 代码组织:该模式有助于将构造逻辑与表示分离,使代码更加模块化且更易于维护。

  4. 可重用性:PromptDirector 类允许我们为不同类型的提示重用相同的构造过程,增强代码的可重用性。

  5. 抽象 :index.ts 中的客户端代码保持简单并专注于高级逻辑,而提示构造的复杂性在构建器类中被抽象化。

接触

如果您有任何疑问或想进一步讨论,请随时与我联系。

编码愉快!

以上是掌握构建器模式:创建动态 AI 提示生成器 CLI的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn