ChatGPTでRAG(Retrieval-Augmented Generation)を試してみた

AIを使った開発をより徹底するために今プロンプトエンジニアリングを研究している。

そんな折Xで面白い資料を見つけたため、さっそく試してみることにした。

RAG(Retrieval-Augmented Generation)ってなによ

LLMと特定の外部データシステムを連携させることで、機能を拡張する方法

なぜRAGが必要か
●能力を強化し、より正確かつ新しい情報を提供するため
○ トレーニングデータに 、最新 情報が含まれていない場合がある
○ AGを使用することで、リアルタイム 情報取得や専門的なトピックに対応できる
(https://speakerdeck.com/mkazutaka/gptsyorijing-du-nogao-iragsisutemunogou-zhu)

RAGは、外部の知識ベースから事実を検索して、最新の正確な情報に基づいて大規模言語モデル(LLM)に回答を生成させることで、ユーザーの洞察をLLMの生成プロセスに組み込むというAIフレームワークです。
(https://www.ibm.com/blogs/solutions/jp-ja/retrieval-augmented-generation-rag/)

Before

まずRAGを使わなかった場合から紹介する。

使ったプロンプトがこう。

Generate a code to create an S3 backet `production_app_log` in Terraform. This bucket will be used to store log files. code only.

結果、ChatGPTから返ってきたのがこうであった。

Here is the Terraform code to create an S3 bucket named `production_app_log` for storing log files:

```hcl
provider "aws" {
    # Specify the AWS region
    region = "us-west-1"  # Change this to your desired AWS region
}

resource "aws_s3_bucket" "production_app_log" {
    bucket = "production_app_log"  # Bucket name

    # Bucket settings for logs
    versioning {
        enabled = true
    }

    lifecycle_rule {
        enabled = true

        noncurrent_version_expiration {
        days = 30
        }
    }

    server_side_encryption_configuration {
        rule {
            apply_server_side_encryption_by_default {
                sse_algorithm = "AES256"
            }
        }
    }

# Additional settings can be added here
}
```

This configuration includes basic settings such as versioning, lifecycle rules for noncurrent versions, and server-side encryption with AES256 algorithm. You can modify the region and add additional settings as needed.

これはこれで別に悪くないのだが、そのまま使うには厳しい。

After

次にRAG(Retrieval-Augmented Generation)を使った場合。

プロンプトはこう。

    Generate a code to create an S3 backet `production_app_log` in Terraform. This bucket will be used to store log files. 

    Please answer by referring to the sample below and outputting only the code.



    ```
    resource "aws_s3_bucket" "deployment" {
    bucket = "${var.environment}-${var.project}-deployment"
    }

    resource "aws_s3_bucket_public_access_block" "deployment" {
    bucket                  = aws_s3_bucket.deployment.id
    ignore_public_acls      = true
    restrict_public_buckets = true
    block_public_acls       = true
    block_public_policy     = true
    }

    data "aws_iam_policy_document" "deployment" {
    statement {
        principals {
        type        = "AWS"
        identifiers = [var.iam.codepipeline_role.arn]
        }

        actions = [
        "s3:Get*",
        "s3:List*",
        "s3:ReplicateObject",
        "s3:PutObject",
        "s3:RestoreObject",
        "s3:PutObjectVersionTagging",
        "s3:PutObjectTagging",
        "s3:PutObjectAcl"
        ]

        resources = [
        aws_s3_bucket.deployment.arn,
        "${aws_s3_bucket.deployment.arn}/*",
        ]
    }
    }

    resource "aws_s3_bucket_policy" "deployment" {
    bucket = aws_s3_bucket.deployment.id
    policy = data.aws_iam_policy_document.deployment.json
    }

    resource "aws_s3_bucket_ownership_controls" "deployment" {
    bucket = aws_s3_bucket.deployment.id
    rule {
        object_ownership = "BucketOwnerEnforced"
    }
    }

    resource "aws_s3_bucket_versioning" "deployment" {
    bucket = aws_s3_bucket.deployment.id
    versioning_configuration {
        status = "Enabled"
    }
    }

    resource "aws_s3_bucket_lifecycle_configuration" "deployment" {
    bucket = aws_s3_bucket.deployment.id

    rule {
        id     = "expire_old_files"
        status = "Enabled"

        expiration {
        days = 365
        }

    }
    }
    ```

返ってきた結果がこう。

```
resource "aws_s3_bucket" "production_app_log" {
bucket = "production_app_log"
}

resource "aws_s3_bucket_public_access_block" "production_app_log" {
bucket                  = aws_s3_bucket.production_app_log.id
ignore_public_acls      = true
restrict_public_buckets = true
block_public_acls       = true
block_public_policy     = true
}

data "aws_iam_policy_document" "production_app_log" {
statement {
    principals {
    type        = "AWS"
    identifiers = [var.iam.logging_role.arn]
    }

    actions = [
    "s3:Get*",
    "s3:List*",
    "s3:PutObject",
    "s3:PutObjectAcl"
    ]

    resources = [
    aws_s3_bucket.production_app_log.arn,
    "${aws_s3_bucket.production_app_log.arn}/*",
    ]
}
}

resource "aws_s3_bucket_policy" "production_app_log" {
bucket = aws_s3_bucket.production_app_log.id
policy = data.aws_iam_policy_document.production_app_log.json
}

resource "aws_s3_bucket_ownership_controls" "production_app_log" {
bucket = aws_s3_bucket.production_app_log.id
rule {
    object_ownership = "BucketOwnerEnforced"
}
}

resource "aws_s3_bucket_versioning" "production_app_log" {
bucket = aws_s3_bucket.production_app_log.id
versioning_configuration {
    status = "Enabled"
}
}

resource "aws_s3_bucket_lifecycle_configuration" "production_app_log" {
bucket = aws_s3_bucket.production_app_log.id

rule {
    id     = "expire_old_files"
    status = "Enabled"

    expiration {
    days = 365
    }

}
}
```

参考コードがテンプレートとして動くのだと思うが、RAGを使わなかった場合と比べてはるかに詳細になっている。aws_iam_policy_documentに設定していたポリシーがはしょられていたりもするが、参考をなにも渡さずに出力させた場合と比べると雲泥の差である。

まあこのような用途であればModuleにしたほうが実際は早いしクオリティが高い。もしそれができないのだとしてもコピペして手動で置換をかけるほうが多分確実だろう。

しかしゼロショットと呼ばれるようなプロンプトを使った場合よりもはるかに求めるものに近いコードが出力されたことは大きな知見である。今後に生かしたい。