ホームページ >ウェブフロントエンド >jsチュートリアル >ビルダー パターンをマスターする: 動的 AI プロンプト ジェネレーター CLI を作成する

ビルダー パターンをマスターする: 動的 AI プロンプト ジェネレーター CLI を作成する

Susan Sarandon
Susan Sarandonオリジナル
2024-11-15 05:30:031047ブラウズ

開発の過程で、複雑なオブジェクトを処理しなければならないケースに遭遇したことがありますか?おそらく、パラメーターが多すぎてネストされる可能性があるか、多くの構築手順と複雑なロジックを構築する必要があるためです。

おそらく、複雑なオブジェクトの作成コードを毎回分散したり考えたりする必要がなく、クリーンで簡単なインターフェイスを備えたモジュールを設計したいと考えているでしょう!

そこでビルダー設計パターンの出番です!

このチュートリアル全体を通じて、ビルダー設計パターンについてすべて説明し、その後、ビルダー設計パターンを使用して DALL-E 3 に最適化されたイメージ生成プロンプトを生成するための CLI Node.js アプリケーションを構築します。 .

最終的なコードは、この Github リポジトリで入手できます。

概要

問題

Builder創造的なデザイン パターン であり、新しいオブジェクトを使用してオブジェクトを作成するネイティブな方法に伴うさまざまな問題に対処するデザイン パターンのカテゴリです。 キーワードまたは演算子。

ビルダー設計パターンは、次の問題の解決に焦点を当てています:

  1. 複雑なオブジェクトを作成するための簡単なインターフェイスを提供します : 多くの初期化手順が必要な、深くネストされたオブジェクトを想像してください。

  2. オブジェクト自体から構築コードを分離し、同じオブジェクトから複数の表現または構成を作成できるようにします。

解決

ビルダー デザイン パターンは、オブジェクト作成の責任をビルダーと呼ばれる特別なオブジェクトに委任することで、これら 2 つの問題を解決します。

ビルダー オブジェクトは元のオブジェクトを構成し、作成プロセスを複数の段階またはステップに分割します。

各ステップは、ビジネス ロジックに基づいてオブジェクト属性のサブセットを初期化するビルダー オブジェクト内のメソッドによって定義されます。

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()

上記のコードからわかるように、クライアント コードはプロンプト 1 またはプロンプト 2 を作成するための詳細を知る必要はありません。ディレクターを呼び出し、正しいビルダー オブジェクトを設定してから、makePrompt メソッドを呼び出すだけです。

実践的なシナリオ

ビルダー設計パターンの有用性をさらに実証するために、

プロンプト エンジニアリング イメージ生成 AI CLI ツールを最初から構築してみましょう。

この CLI アプリのソース コードはここから入手できます。

CLI ツールは次のように動作します:

    CLI は、ユーザーにプロンプ​​トのスタイルのいずれかを選択するよう求めます: リアリスティックまたはデジタル アート。
  1. 次に、プロンプトの件名を入力するようユーザーに求めます (例: ハンバーガーを食べているチーズなど)。
  2. 選択 (デジタル アートまたはリアリスティック) に応じて、CLI ツールは多くの構成詳細を含む複雑なプロンプト オブジェクトを作成します。
現実的なプロンプトを構築するには、次のすべての構成属性が必要です。

ファイル:prompts.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()
  }
}

ファイル:prompts.ts


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

ここでわかるように、各プロンプト タイプでは、

artStylecolorPalettelightingEffectperspective 、カメラタイプ 、など プロジェクトの

enums.ts

ファイルで定義されているすべての属性の詳細を自由に調べてください。

enums.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 では大きな問題ではありません。すべてのプロパティが null 許容である構成オブジェクトを渡すことができるためです。

プロンプトを構築するプロセスを抽象化し、コードを 拡張に対してオープンにし、変更に対してクローズ (SOLID の O) にし、ライブラリ クライアントがプロンプト生成ライブラリをシームレスまたは簡単に使用できるようにするため、 ビルダー設計パターンを実装することを選択します。

汎用プロンプトビルダーインターフェイスを宣言することから始めましょう。

インターフェースは一連のメソッドを宣言します:

  1. buildBasePropertiesbuildTechnicalDetails 、および buildArtisticElements は、Realistic または Digital 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 ファイル内のクライアント コードが簡素化されます。これについては次のセクションで説明します。

serializers.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. inquirer パッケージを使用してプロンプト スタイルを選択し、次に件名を選択するようにユーザーに求めます: getUserInput.
  2. ユーザーから件名とアート スタイルの両方を取得した後、クライアント コードはライブラリから PromptBuilderDirector の 2 つのコンポーネントのみを使用します。
  3. まず、Director をインスタンス化します。
  4. 次に、選択したプロンプト スタイルに応じて、対応するビルダーをインスタンス化し、それを Director クラスに設定します。
  5. 最後に、選択したサブジェクトを引数として director.makePrompt メソッドを呼び出し、 builder からプロンプトを取得し、シリアル化されたプロンプトを端末コンソールに出力します。

覚えておいてください: 各ビルダー タイプによって生成されるプロンプトの形状は異なるため、ディレクターからプロンプトを取得することはできません。

結論

AI 画像プロンプト生成 CLI アプリケーションで実証されているように、Builder デザイン パターンは、複数の構成を持つ複雑なオブジェクトを作成するための優れたソリューションであることが証明されています。このシナリオで Builder パターンが有益である理由は次のとおりです:

  1. 簡略化されたオブジェクト作成 : このパターンにより、複雑な構築プロセスをクライアント コードに公開することなく、複雑な RealisticPhotoPrompt オブジェクトと DigitalArtPrompt オブジェクトを作成できました。

  2. 柔軟性 : プロンプト タイプごとに個別のビルダー クラスを使用することで、クライアント コードを変更せずに、新しいプロンプト タイプを簡単に追加したり、既存のプロンプト タイプを変更したりできます。

  3. コード構成 : このパターンは、構築ロジックを表現から分離するのに役立ち、コードをよりモジュール化して保守しやすくしました。

  4. 再利用性 : PromptDirector クラスを使用すると、異なる種類のプロンプトに対して同じ構築プロセスを再利用できるため、コードの再利用性が向上します。

  5. 抽象化 :index.ts のクライアント コードはシンプルなままで高レベルのロジックに重点を置いていますが、プロンプト構築の複雑さはビルダー クラスで抽象化されています。

接触

ご質問がある場合、またはさらに詳しく話し合いたい場合は、お気軽にこちらまでご連絡ください。

コーディングを楽しんでください!

以上がビルダー パターンをマスターする: 動的 AI プロンプト ジェネレーター CLI を作成するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。