使用ChatGPT开发云应用时发生了什么?

56 阅读5分钟

正如你所知,ChatGPT将颠覆简单的程序员。因此,我尝试了一下完全使用ChatGPT开发云应用的情况。( 实际上我使用了带有GPT-4模式的ChatGPT Plus。)

总结

ChatGPT对于加速我们在开始阶段的开发速度非常有用。但是,当我们无法充分使用ChatGPT(实际上不仅仅是ChatGPT还包括其他的AI)时,GIGO(垃圾进垃圾出)定律是真实的。这取决于我们如何充分利用ChatGPT。

前提条件

这一次,我创建了几个代码来爬取Amazon产品页面。但是,Amazon禁止了爬取,我在开始之前没有注意到这一点。

概观

我向ChatGPT发送了以下消息(用日语),这对于人力开发人员来说也显得太粗糙了:)

你是一名软件工程师,需要创建一个应用程序,可以通知特定产品的价格将要变化,并通知我。

# 规格说明。
1. 在开发中使用以下技术。
   1) 处理:Python
      A) 从数据库中读取产品代码并访问Amazon产品页。
      B) 从产品页检索价格并将其与上一价格进行比较。
      C) 如果价格低于上一个价格,请在Slack上通知。
   2) 数据库:MySQL
      DB中存储以下内容。
      A) 产品代码
      B) 产品价格(先前价格)

   3) 价格更改时的通知目的地:Slack

2. 该应用程序应为在AWS EC2上运行的独立应用程序。
3.该程序将每小时启动一次。

# 交付成果
1. 数据库建立DDL。
2. Python程序。
3. 用于在EC2上构建它们的CloudFormation模板。

输出代码应为可复制格式。

简单的应用程序结构如下。

Image description
(上图忽略了SSM)

ChatGPT的答复

有几个小错误在我进行了审查后,ChatGPT帮我进行了纠正,但几乎是这个结果。乍一看,这似乎是正确的,甚至有点可怕。并且还可以生成CloudFormation (CFn)模板,这使我感到惊讶。
(底部包含所需的通信详细信息。)

DDL:

CREATE TABLE `product_price` (
  `product_code` varchar(50) NOT NULL,
  `price` decimal(10,2) DEFAULT NULL,
  PRIMARY KEY (`product_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Python代码(现在已禁止Amazon页面爬取,因此我删除了相关代码)

import os
import boto3
import requests
from bs4 import BeautifulSoup
import pymysql
import logging
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

region_name = os.environ["AWS_REGION"]
ssm = boto3.client("ssm", region_name=region_name)
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

# Database connection information
DB_ENDPOINT = ssm.get_parameter(Name='/cgpt-amazon-price-alert/db-endpoint', WithDecryption=True)['Parameter']['Value']
DB_USER = ssm.get_parameter(Name='/cgpt-amazon-price-alert/db-user', WithDecryption=True)['Parameter']['Value']
DB_PASSWORD = ssm.get_parameter(Name='/cgpt-amazon-price-alert/db-password', WithDecryption=True)['Parameter']['Value']
DB_NAME = ssm.get_parameter(Name='/cgpt-amazon-price-alert/db-name', WithDecryption=True)['Parameter']['Value']

# Slack Bot connection information
SLACK_BOT_TOKEN = ssm.get_parameter(Name='/cgpt-amazon-price-alert/slack-bot-token', WithDecryption=True)['Parameter']['Value']
SLACK_CHANNEL = ssm.get_parameter(Name='/cgpt-amazon-price-alert/slack-channel', WithDecryption=True)['Parameter']['Value']

# Database connection
conn = pymysql.connect(host=DB_ENDPOINT, user=DB_USER, password=DB_PASSWORD, database=DB_NAME)

# Slack Notify
def notify_slack(message):
    try:
        client = WebClient(token=SLACK_BOT_TOKEN)
        response = client.chat_postMessage(channel=SLACK_CHANNEL, text=message)
    except SlackApiError as e:
        logger.error("Error sending message: {}".format(e.response['error']))

def get_price(url):
    ### Deleted because scraping Amazon website is prohibited now. ###

def main():
    # Get product information from Database
    cursor = conn.cursor()
    cursor.execute("SELECT product_code, price FROM product_price")
    rows = cursor.fetchall()

    # Get Amazon product price and compare with previous one.
    for row in rows:

        # Get the price from Amazon
        product_code, previous_price = row
        url = f"https://www.amazon.co.jp/dp/{product_code}"
        current_price = get_price(url)

        # Comparing with previous price
        if current_price < previous_price:
            message = f"Product {product_code}  price was lower than before. Previous price: {previous_price} Yen, Current price: {current_price} Yen"
            notify_slack(message)

            # Update DB product information.
            cursor.execute("UPDATE products SET price=%s WHERE product_code=%s", (current_price, product_code))
            conn.commit()

if __name__ == "__main__":
    main()

SSM的必要密钥注册:

aws ssm put-parameter \
    --name "/cgpt-amazon-price-alert/db-endpoint" \
    --value "your_db_endpoint" \
    --type "SecureString"

aws ssm put-parameter \
    --name "/cgpt-amazon-price-alert/db-user" \
    --value "your_db_username" \
    --type "SecureString"

aws ssm put-parameter \
    --name "/cgpt-amazon-price-alert/db-password" \
    --value "your_db_password" \
    --type "SecureString"

aws ssm put-parameter \
    --name "/cgpt-amazon-price-alert/db-name" \
    --value "your_db_name" \
    --type "SecureString"

aws ssm put-parameter \
    --name "/cgpt-amazon-price-alert/slack-bot-token" \
    --value "your_slack_bot_token" \
    --type "SecureString"

aws ssm put-parameter \
    --name "/cgpt-amazon-price-alert/slack-channel" \
    --value "your_slack_channel" \
    --type "SecureString"


CloudFormation模板:

---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  VpcId:
    Type: AWS::EC2::VPC::Id
    Description: "VPC ID"
  SubnetId:
    Type: AWS::EC2::Subnet::Id
    Description: "Subnet ID"
Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Metadata:
      AWS::CloudFormation::Init:
        config:
          commands:
            01_install_mysql:
              command: |
                amazon-linux-extras install -y epel
                yum install -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
                yum --nogpgcheck install -y mysql-community-server
                systemctl start mysqld
                systemctl enable mysqld
            02_generate_password:
              command: |
                echo $(grep 'temporary password' /var/log/mysqld.log | awk '{print $NF}') > /tmp/mysql_root_password
            03_install_slack_sdk:
              command: |
                yum install -y python3-pip
                pip3 install slack-sdk
            04_install_beautifulsoup4:
              command: |
                pip3 install beautifulsoup4
            05_install_lxml:
              command: |
                pip3 install lxml
            06_install_requests:
              command: |
                pip3 install requests
          services:
            sysvinit:
              mysqld:
                enabled: true
                ensureRunning: true
    Properties:
      ImageId: ami-05b5badc2f7ddd88d
      InstanceType: t3.micro  # Instance Type
      KeyName: cgpt-amazon-price-alert-key  # Keypair name for connection to EC2 instance.
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash
          echo "export AWS_REGION=${AWS::Region}" >> /etc/profile.d/aws_region.sh
          chmod +x /etc/profile.d/aws_region.sh
          source /etc/profile.d/aws_region.sh
          /opt/aws/bin/cfn-init --stack ${AWS::StackName} --resource EC2Instance --region ${AWS::Region}
          yum update -y
          yum install -y python3
          pip3 install boto3
          pip3 install pymysql
          pip3 install slack-sdk
          mkdir /app
          touch /app/check_price.py
          touch /var/log/check_price.log
          chown ec2-user:ec2-user /var/log/check_price.log
          echo '*/1 * * * * ec2-user /usr/bin/python3 /app/check_price.py' > /etc/cron.d/check_price-cron
      IamInstanceProfile: !Ref InstanceProfile
      NetworkInterfaces:
        - AssociatePublicIpAddress: true
          DeviceIndex: 0
          GroupSet:
            - !Ref InstanceSecurityGroup
          SubnetId: !Ref SubnetId
  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow SSH access
      VpcId: !Ref VpcId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
  InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref InstanceRole
  InstanceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: SSMParameterAccess
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - ssm:GetParameter
                Resource: "*"

我使用ChatGPT准备MySQL DB初始化所需的时间比较长,因此我使用ChatGPT创建了shell脚本。(实际上以下代码有一些不安全的部分"密码直接输入",最好不要使用。)

#!/bin/bash

# Variables
initial_password="your_initial_password"
new_password="your_new_password"

# Log in to MySQL and execute commands
mysql -u root -p"${initial_password}" <<EOF
-- Change the initial password
ALTER USER 'root'@'localhost' IDENTIFIED BY '${new_password}';

-- Create the amazonprice database
CREATE DATABASE amazonprice;

-- Use the amazonprice databse
USE amazonprice;

-- Create the product_price table
CREATE TABLE product_price (
  product_code VARCHAR(50) NOT NULL,
  price DECIMAL(10,2) DEFAULT NULL,
  PRIMARY KEY (product_code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- Insert sample data into the product_price table
INSERT INTO product_price (product_code, price) VALUES ('your_price_code', 1000.00);
EOF

它们的执行过程:

chmod +x setup_mysql.sh
./setup_mysql.sh

结论

如我在开头所提到的,这似乎是一个非常强大的服务,可以增加开发的初始速度。然而,如果你试图做比提高初始速度更多的事情,那么将会花费很多时间,所以现在,我认为最好在开发的早期使用它。

需要注意的是,代码完成了很多我想要指出的内容,例如在UserData中挖掘根目录中的文件夹,只有root可以访问它,或异常处理等等。我没有用它来得到报酬。

(附录)我需要与ChatGPT多次通信的内容

开始时我提到的第一条消息中有几个不完整的部分。因此,我多次与ChatGPT进行沟通以提高质量。

总的来说,我与ChatGPT的通信达到了40到50次。

以下是我多次交流的主要部分。

  1. 像DB_ENDPOINT这样的值被定义在环境变量中。 →改进以从SSM获取它们。
  2. CFT(CloudFormation Template)中有关所需库的安装描述不够详细。
  3. VPC / Subnet等没有被描述,因此无法生成CFn堆栈。
  4. 多次通信后,之前的修改点下降了。 我不想做到这样类似于人:)
  5. MySQL安装未包含在CFn模板中。
  6. 存在"Userdata"中未列出Metadata的问题,因此未执行Metadata部分。
  7. MySQL安装中有几个错误,包括GPG密钥错误。
  8. 缺少访问AWS资源的区域规范和附加到EC2的IAM角色设置。
  9. 即使Amazon有反爬虫措施,ChatGPT也提供了爬虫代码。(在这种情况下,我没有修改代码来使用Amazon API,但是如果我明确指定要使用AmazonAPI,ChatGPT可以生成它。)