Amazon Web Services ブログ

Amazon CodeWhispererを使ったプロンプトエンジニアリングのベストプラクティス

生成 AI コーディングツールは、開発者の日々の開発作業の仕方を変えています。関数の生成からユニットテストの作成まで、これらのツールはお客様のソフトウェア開発の加速に役立っています。 Amazon CodeWhisperer は、開発者の自然言語のコメントと周囲のコードに基づいてコードのレコメンデーションを提供することで、開発者の生産性を向上させる IDE とコマンドラインの AI による生産性向上ツールです。 CodeWhisperer を使用すると、開発者は「 S3 にファイルをアップロードする Lambda 関数を作成する」など、特定のタスクを簡単な英語で概説するコメントを単純に記述することができます。

CodeWhisperer に対してこれらの自然言語のコメントのような入力プロンプトを記述する際、プロンプトエンジニアリングは重要な概念の1つです。 プロンプトエンジニアリングは大規模言語モデル (LLM) との対話を改善して、モデルの出力をより良いものにするプロセスです。 私たちは CodeWhisperer に提供するプロンプトを改善して、より良いコード出力を生成したいと考えています。

この投稿では、Python における効果的なプロンプトエンジニアリングを通じて、 CodeWhisperer の機能を最大限に活用する方法を探っていきます。巧みに作られたプロンプトにより、ツールの全能力を引き出し、生産性を向上させ、使用目的に合った正しいコードを生成するのに役立ちます。明確で具体的なプロンプトの記述や、有益なコンテキストと例の提供など、プロンプトエンジニアリングのベストプラクティスについて説明します。また反復的にプロンプトを改良して、より良い結果を生み出す方法についても議論します。

CodeWhisperer を使ったプロンプトエンジニアリング

CodeWhisperer を使ったプロンプトエンジニアリングにおいて、以下のベストプラクティスをデモンストレーションします。

  • プロンプトは具体的かつ簡潔に保つ
  • プロンプトでの追加のコンテキスト
  • 複数のコメントの利用
  • コメントとコードからのコンテキストの取得
  • クロスファイルコンテキストでのユニットテストの生成
  • クロスファイルコンテキストを持つプロンプト

前提条件

ローカルで検証するために必要な前提条件は以下のとおりです。

CodeWhisperer ユーザーアクション

IDE に応じた CodeWhisperer ユーザーアクションの以下のドキュメントを参照してください。このドキュメントでは、レコメンデーションを受け入れる方法、推奨オプションを順に切り替える方法、推奨を拒否する方法、CodeWhisperer を手動でトリガーする方法が説明されています。

プロンプトを具体的かつ簡潔に保つ

このセクションでは、プロンプトを具体的かつ簡潔に保つ方法を説明します。CodeWhisperer のプロンプトを作成する際、プロンプトの目的を維持しつつ簡潔であることは重要な要素です。 過度に複雑なプロンプトは結果を悪くします。 良いプロンプトには、要求を明確かつ簡潔に伝えるのに必要な情報が含まれています。 例えば、 CodeWhisperer に 「create a function that eliminates duplicates lines in a text file」 とプロンプトするとします。 これは具体的かつ簡潔なプロンプトの例です。 一方、 「create a function to look for lines of code that are seen multiple times throughout the file and delete them」 などのプロンプトは不明確で冗長すぎる可能性があります。 まとめると、焦点を絞った直接的なプロンプトは CodeWhisperer があなたが何を望んでいるかを正確に理解し、より良いレコメンデーションを提供するのに役立ちます。

この例では、 Python で CSV ファイルを開き、ファイルの内容を辞書に格納する関数を書きたいと思います。 以下のシンプルかつ簡潔なプロンプトを使用して、 CodeWhisperer にレコメンデーションを生成させます。 レコメンデーションを受け入れる前に、左/右の矢印キーを使用して、さまざまな推奨事項を順に表示してください。

例 1:

コメントの例:

#load the csv file content in a dictionary

ソリューションの例:

#load the csv file content in a dictionary
import csv
def csv_to_dict(csv_file):
    with open(csv_file, 'r') as f:
        reader = csv.DictReader(f)
        return list(reader)

簡潔で明確なプロンプトは、プロンプトエンジニアリングにおいて重要です。なぜなら、それらは CodeWhisperer が余計な詳細に惑わされることなく、重要な情報を理解するのに役立つからです。シンプルで簡潔なプロンプトは、反復のスピードを上げ、文字数制限内で最大限の効果を発揮できるようにします。

プロンプトの追加のコンテキスト

このセクションでは、追加のコンテキストがプロンプトエンジニアリングをどのように支援できるかを説明します。詳細で具体的かつ簡潔なプロンプトが重要ですが、追加のコンテキストは CodeWhisperer の理解を助けることができます。具体例は簡潔なプロンプトからのユーザーの要求を CodeWhisperer が推測するのが困難な場合にも、ガイドラインを提供します。

この例では、 CSV ファイルのコンテンツを辞書に格納した例1に追加のコンテキストを加えたいと思います。今回は、アルファベット順に CSV ファイルのコンテンツを格納し、辞書からキーリストを返す追加の要件があります。以下のサンプルプロンプトをご覧ください。適切なコンテキストは、 CodeWhisperer が高品質でカスタマイズされたレコメンデーションを生成するのに役立ちます。

例 2:

コメントの例:

#load the csv file content in a dictionary in alphabetical order and return the list of keys

ソリューションの例:

#load the csv file content in a dictionary in alphabetical order and return the list of keys
import csv
def csv_to_dict(file_name):
    def read_csv_file(file_name):
    with open(file_name, 'r') as csv_file:
        csv_reader = csv.DictReader(csv_file)
        csv_dict = {}
        for row in csv_reader:
            csv_dict[row['name']] = row
            return csv_dict

プロンプトを CodeWhisperer に提示する際、背景の詳細や例を通じて追加のコンテキストを提供することは有益です。ただし、その追加情報が本質的な要求を曖昧にするのではなく、有用な明確さを加える場合に限ります。簡潔さと的を射たコンテキストのシグナルの適切なバランスは、 CodeWhisperer がより適合性の高い高品質なレコメンデーションを生成するのに役立ちます。

複数のコメントを利用する

このセクションでは、プロンプトエンジニアリングにおいて、複数のコメントがどのように有用なテクニックとなりうるかを説明します。戦略的に CodeWhisperer を使用することで、複数のコメントにより、簡潔さを犠牲にすることやプロンプトを乱雑にさせることなく、より多くのコンテキストを提供できます。

例えば、 CSV ファイルを開き、その中の行をアルファベット順に並べ替え、重複行を削除し、各行の末尾にピリオドを追加して返す、ということをしたいとします。以下の CodeWhisperer のプロンプトを見てください。複数の要件を別々のコメントに分割していることに注目してください。

例 3:

コメントの例:

#open a csv file and return a list of lines in alphabetical order
#Remove duplicate lines
#Insert a period at the end of each line

ソリューションの例:

#open a csv file and return a list of lines in alphabetical order
#Remove duplicate lines
#Insert a period at the end of each line
def open_csv(filename):
    with open(filename) as f:
        lines = f.readlines()
        lines = list(set(lines))
        lines = sorted(lines)
        for i in range(len(lines)):
            lines[i] = lines[i].rstrip() + '.'
    return lines

複数のコメントを許可することで、プロンプトを簡潔に保ちながら、拡張されたコンテキストとガイダンスを CodeWhisperer に追加できるようになります。

コメントとコードから得られたコンテキスト

このセクションでは、 CodeWhisperer のコンテキストがコメントだけでなく、周辺のコード(他の関数、インポートなど)も参照していることを説明します。この拡大されたコンテキストにより、 CodeWhisperer はコメントで意図したユースケースを実装するのに役立ちます。

ここでは、プロジェクト内の追加のコードがレコメンデーションにどのように影響するかを見ていきます。今回は Pandas ライブラリをインポートして、前のセクションと比較してレコメンデーションがどのように変化するかを確認します。

例 4:

コメントの例:

import pandas as pd 
#open a csv file and return a list of lines in alphabetical order
#Insert a period at the end of each line
#Replace duplicate lines with a single line

ソリューションの例:

import pandas as pd
#open a csv file and return a list of lines in alphabetical order
#Insert a period at the end of each line
#Replace duplicate lines with a single line
def open_csv(filename):
    df = pd.read_csv(filename)
    df = df.sort_values(by='line')
    df = df.drop_duplicates(subset='line')
    df['line'] = df['line'] + '.'
    return df['line'].tolist()

Pandas をインポートすることで、 CodeWhisperer はソリューションでそれを活用する意図があると理解しています。これにより、 read_csv() 、 sort_values() 、 drop_duplicates() などの Pandas 関数を使用した、より関連性の高いレコメンデーションを提供できます。

コードの周囲のコンテキストは、おおまかな指示における実装の意図について、 CodeWhisperer に追加の手がかりを提供します。

クロスファイルコンテキストを用いたプロンプト

前のセクションでは、 CodeWhisperer がコンテキストとして取り込む周囲のコードを利用することで、ユースケースに合わせた関数を生成できることを確認しました。このセクションでは、 CodeWhisperer のクロスファイルコンテキスト機能を用いて、構築した関数のためのユニットテストを生成します。このセクションでは、テスト駆動開発のようなユースケースでクロスファイルコンテキストを用いたプロンプトの使い方をデモンストレーションします。

この例では、 CodeWhisperer に open_csv 関数を参照するコメントを書かせることで、ユニットテストを記述します。この場合、プロジェクトディレクトリにユニットテスト専用の新しい Python ファイルがあるとします。これまで作業してきたファイルが 「example4.py」 で、新しいファイルが 「unittest.py」 だとします。 「unittest.py」 に以下のコメントを含めます。

例 5:

unittest.py のコメントの例:

#create unit tests for the open_csv function from example4.py file

unittest.py のソリューションの例:

#create unit tests for the open_csv function from example4.py file
class TestOpenCsv(unittest.TestCase):
   def test_open_csv(self):
       self.assertEqual(open_csv('example4.csv'), ['a.', 'b.', 'c.'])
       self.assertEqual(open_csv('example4.csv'), ['a.', 'b.', 'c.', 'd.'])

CodeWhisperer が 1 つのファイルのコンテキストを使って、別のファイルでコードのレコメンデーションを生成していることに注目してください。 「unittest.py」 のコメント内で open_csv 関数を指定することで、 CodeWhisperer はその関数の目的とインターフェースを分析し、理解することができ、それを検証するための基本的な単体テストのセットを生成することができました。プロンプトを使うことで、クロスファイルのコンテキストを利用して単体テストを生成することができました。

Chain of thought (思考の連鎖) プロンプティング

Chain of thought (思考の連鎖) プロンプティングは、複数のプロンプトをつなげることで、大規模言語モデル (LLM) がより自然なコンテキストを考慮した出力を生成できるようにするプロンプトエンジニアリングの手法です。 CodeWhisperer を利用する際、この手法を用いて非常に複雑なコーディングタスクを小さなステップに分解することによって、 CodeWhisperer がユースケースに対してより正確なレコメンデーションを行うことができます。

この例では、 CodeWhisperer によって生成されたコードスニペットで、複数のコメントが含まれているものを検証します。目的は、ユーザーにファイル名の入力を促し、それが csv かつアルファベット数字であることを確認した上で、 logging.info メソッドで処理することです。 Chain of thought (思考の連鎖) によるアプローチと単一のコメントの 2 通りで出力を分析します。

例 6:

Chain of thought (思考の連鎖) プロンプトアプローチ:

コメント 1 – “Take a user’s input using the input() function and store it in a variable called filename”

import logging 
# Take a users input using the input() function and store it in a variable called filename 
filename = input("Enter the name of the file you want to read: ")

コメント 2 – “create a function that will take a filename as an input”

import logging 
# Take a users input using the input() function and store it in a variable called filename 
filename = input("Enter the name of the file you want to read: ")
#create a function that will take a filename as an input
def open_file(filename):

コメント 3 – “validate the input using the isalnum() method and ensure the file ends in .csv then process the file using logging.info()”

import logging
# Take a users input using the input() function and store it in a variable called filename
filename = input("Enter the name of the file you want to read: ")

#create a function that will take a filename as an input
def open_file(filename):
    #validate the input using the isalnum() method and ensure the file ends in .csv then process the file using logging.info() 
    if filename.isalnum() and filename.endswith('.csv'):
        lines = open_csv(filename)
        logging.info(lines)
        return lines
    else:
        print('Invalid file name')
        return None

単一プロンプトによるアプローチ:

import logging
'''
Using the input() function and store it in a variable called filename and create a function 
that will validate the input using the isalnum() method and ensure the file ends in .csv then process 
the file accordingly. 
'''
def validate_file(filename):
    if filename.isalnum() and filename.endswith('.csv'):
        return True
    else:
        return False

これらを並べて分析すると、 Chain of thought (思考の連鎖) プロンプトアプローチを用いた場合、ユーザー入力、入力検証、 .csv の検証、ログ記録など、 CodeWhisperer にすべての要件を実装させるために、複数のコメントを使用したことがわかります。一方、複数の要件を 1 つのコメントで実装したケースでは、この少し複雑な問題のすべての要件を考慮していなかったことがわかります。

結論として、 Chain of thought (思考の連鎖) プロンプトは CodeWhisperer のような大規模な言語モデルが、複雑な問題を論理的なステップに分解することで、使用例に関してより正確なコードを生成できるようにします。コメントとプロンプトでモデルを導くことで、タスクの各部分に順を追って集中できるのです。その結果、広範囲な 1 つのプロンプトと比較して、目的の機能により適合した正確なコードが生成されます。

まとめ

効果的なプロンプトエンジニアリングは、 Amazon CodeWhisperer のような強力な AI コーディングアシスタントを最大限に活用するための鍵です。具体的な説明、コンテキストの提供、プロンプトの反復的な改良などのプロンプトのベストプラクティスに従うことで、 CodeWhisperer はニーズに合わせた高品質なコードを生成するのに役立ちます。 CodeWhisperer が提供するすべてのコードオプションを分析することで、最適なアプローチを選択する柔軟性が得られます。

翻訳はソリューションアーキテクトの紙谷が担当しました。原文はこちらです。

著者について

Brendan Jenkins

Brendan Jenkins

Brendan Jenkins は、Amazon Web Services (AWS) のソリューションアーキテクトで、エンタープライズの AWS カスタマーに技術的なガイダンスを提供し、ビジネス目標の達成を支援しています。彼は DevOps と機械学習技術を得意としています。

Riya Dani

Riya Dani

Riya Dani は、Amazon Web Services (AWS) のソリューションアーキテクトで、エンタープライズのお客様がクラウドへの移行を進める際の支援を担当しています。学びに対する情熱を持ち、バージニア工科大学でディープラーニングに焦点を当てたコンピューターサイエンスの学士号と修士号を取得しています。自由時間には、アクティブに過ごしたり読書を楽しんでいます。