【生成AI】知らないと後悔する、GPT-4oだけでシステム開発を300%効率化するハック【CodeAGI】

::: note
こちらの記事は投稿時点の情報です。
また、本稿は**個人の見解に基づいた内容**であり、**所属する会社の公式見解ではありません**。
:::

都内のIT企業に勤めている、ソフトウェアエンジニアの D̷ELL と申します。
本稿はQiita Engineer Festa 2024の参加記事です。

本日は生成AI（GPT-4o）のAPIキーだけで、システム開発を300%効率化するハックを共有したいと思います。

# 概要
- 生成AIによるアプリケーション開発自動化が実現しつつある時代になってきた
- 日本企業における「Excelドキュメント」は数多く、生成AIを実践投入しづらい
- GPT-4oのAPIキーさえあれば、社内のドキュメントからシステムを自動構築してくれる仕組みがあった

# はじめに
みなさんはアプリケーション開発における生成AIの利用と言えば、何を想像しますか？おそらく大半の方が、ChatGPTやCopilotを用いた「コード生成の補助」ですよね。プロンプトを渡せば、特定のファイルのコードを修正したり、自動生成したりしてくれます。

最近では、アンソロピック社のClaude 3.5 Sonnetによって、プロンプトからSPA（Single Page Application）の生成や、動作確認がブラウザで完結できるようになりました。
Claude 3.5 Sonnectの良い点は、既存の生成AIと違い「複数のファイルを生成した上で結合して動作させてくれる点」でした。ここまで来ると、もはや「アプリケーション開発の自動化」と呼んでも差し支えないのでは、と思います。

## 我々の夢の終着点はここだったのか？
上記の通り、現在、人々が夢見てきた「AIによるアプリケーション開発の自動化」が、生成AIによって実現しつつある時代です。しかし、ChatGPTで生成できるコードは、せいぜい数ファイル規模。Claude 3.5 Sonnetで生成できる言語はまだ限られているのが現状です。やはりまだ「Copilot（副操縦士）」の域を出ないと感じている方が多いと思います。

つまり、有史以来「仕様書からプログラムすべて起こしてほしい」という夢物語はいまだ実現が難しい状況です。やはり銀の弾丸は実現しえないのでしょうか。

## 銀の弾丸は存在しないが、銀の弾丸に近づくことはできる
そんな中、GPT-4のAPIキーさえあれば、**アプリケーション開発からテストコードの作成、及びテストデータまで自動構築する仕組み** が登場しました。アプリケーション開発に超特化した、生成AIをラップした自律型エージェントです。

それが、設計書からプログラムコードを自動生成するサービス **CodeAGI**です。これは、ドキュメントを読み込ませるだけで、読み込んだドキュメントを解析し、指定した言語でアプリケーションを開発し、スキーマを構築し、テストコードとテストデータを作成できる、 **銀の弾丸に挑戦するかのようなシステム** です。

本稿では、**CodeAGI**を使って実際にアプリケーション開発を自動化したレポートと、その実用例について解説していきます。

# CodeAGIとは？

Qiita Engineer Festa 2024のCodeAGIのページから説明を見てみましょう。

https://qiita.com/official-events/579a875535f3fa987106

> 設計書からプログラムコードを自動生成するサービス ”CodeAGI”
> 様々な設計書をインプットするだけで、設計書を解析の上プログラムを自動生成できるAI技術です。
>
> CodeAGIだけが実現できる6つのこと
> - 企業独自の多様なフォーマットの設計書解析を実現
> - 設計書やデータ構造を学習し整合性を担保した正確なコード自動生成を実現
> - リレーショナルデータベースの解析による複雑なSQLの自動生成を実現
> - テストケース・テストデータの生成を実現
> - 画像データを解析することで、画面プログラムのコード生成を実現
> - 複数プログラムの一括自動生成を実現

エンジニアの夢がてんこ盛りですね。眉唾ものです。
なんと **利用料無料で、生成されたプログラムの著作権もフリー** とのこと。試さない手はありません。
> CodeAGIβver の使用は現在オールフリー（無料）です。
> 生成されたプログラムコードの著作権はフリーであり商用利用も可能です。

APIキーだけ自身で準備する必要がありますが、自分の好きな生成AIアプリケーションのAPIを選べるとのことで、そこも私は魅力に感じました。

## 技術的な開発背景
開発元であるSOPPRA Digital transformation 株式会社は、AIeSという独自の自然言語解析エンジンを開発しているとのこと。これを生成AIと組み合わせることにより、様々なドキュメントの解析を可能にしているとのことです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/71017ccf-e475-fc41-aeb3-aa7f47cc97e3.png)

## 300%の効率化
実際に利用した場合の効率化は、 5人日の作業が1.5人日になるとのこと。実に **333%の効率化** ですね。j後述しますが、実際にCodeAGIは導入ハードルが極めて低く、利用までの学習コストも低いため、この数値はあながち嘘ではないかなと感じました。
このあとのレビューを読んで頂ければ、それが実感いただけると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/7981491a-e7ee-17e3-c6b3-86b666fabcc5.png)


それでは、さっそくインストールしていきます。


## インストール
CodeAGIは以下のサイトからインストールできます。

https://www.soppradx.com/service.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/3875e1e7-3d87-34ff-ede0-932db41f6a60.png)

:::note info
会員登録が必要ですが、最低限の入力項目でしたので、本稿では割愛します
:::

Windowsアプリで提供されており、数分でインストールが完了しました。
それでは使っていきましょう。

**なお、Qiitaで提供されたクイックマニュアルは以下の一枚だけ。**
公式ホームページにはマニュアルがあるのですが、Qiitaからすれば「エンジニアはどうせマニュアルなんて読まないだろ」ってことかもしれません。よくわかっていらっしゃる。
技術屋が作ったシステムって感じで大好きです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/f2d94996-932b-8b1e-8ce9-52a64219850b.png)

なお、公式マニュアルは[こちら](https://www.soppradx.com/download/CodeAGI%E6%93%8D%E4%BD%9C%E3%83%9E%E3%83%8B%E3%83%A5%E3%82%A2%E3%83%AB.pdf)です。

### 初期設定

アプリを起動して、生成AIの設定を行います。エンジンを選んで、API Keyを入力して、モデルを選択できます。このへんの気遣いもありがたいですね。

:::note info
OpenAIなどのモデルは動的に更新されるため、適宜サーバーから取得して指定できることで、今後のAPIの更新にも柔軟に対応できます。また、各社の高性能なモデルを選定できることも強みです。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/b0f8c249-354a-1907-dc26-5741d130ebd9.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/ab6e5a48-be5a-4c7c-f28d-b22a47003ede.png)


## プロジェクト情報の入力

プロジェクトを選択 → プロジェクト情報から、作成するプロジェクトの情報を入力します。
入力項目は直感でいけますが、設定できる項目と入力例を列挙しておいたのでご参照ください。

:::note warn
あくまで私個人の設定ですので、ご参考までにお願いいたします。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/150f16a8-b5ba-e81b-3a2e-354081729643.png)

- プロジェクト名 ... プロジェクトの名前を入力します
- プロジェクト説明 ... プロジェクトの概要や目的を記述します
- コード出力先フォルダ ... 生成されたコードを保存するフォルダのパスを指定します
- テストケース・データ出力先フォルダ ... テストケースや関連データを保存するフォルダのパスを指定します
- OS ... 開発環境のオペレーティングシステムを指定します（例: Windows, macOS, Linux）
- DB ... プロジェクトで使用するデータベースの種類を指定します（例: MySQL, PostgreSQL, MongoDB）
- ブラウザ ... 開発やテストに使用するブラウザを指定します（例: Chrome, Firefox, Safari）
- 生成プログラムに画面ID・バッチIDを使う（True/False） ... 生成プログラムで画面IDやバッチIDを使用するかどうかを指定します（Trueの場合は使用、Falseの場合は不使用）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/91fbacce-7ba3-e27e-995e-cd6b6817951d.png)

- プロジェクト依存環境設定
    - 画面（フロントエンド）
        - プログラミング言語 ... フロントエンド開発に使用するプログラミング言語を指定します（例: JavaScript, TypeScript）
        - フレームワーク ... フロントエンド開発に使用するフレームワークを指定します（例: React, Angular, Vue.js）
        - パッケージ ... フロントエンドで使用する主要なパッケージやライブラリを指定します（例: Webpack, Bootstrap）
    - 画面（バックエンド）／API
        - プログラミング言語 ... バックエンド開発に使用するプログラミング言語を指定します（例: Java, Python, Node.js）
        - フレームワーク ... バックエンド開発に使用するフレームワークを指定します（例: Spring Boot, Django, Express.js）
        - パッケージ ... バックエンドで使用する主要なパッケージやライブラリを指定します（今回は未指定）
    - バッチ
        - プログラミング言語 ... バッチ処理に使用するプログラミング言語を指定します（例: Python, Java, Bash）
        - フレームワーク ... バッチ処理に使用するフレームワークを指定します（今回は未指定）
        - パッケージ ... バッチ処理で使用する主要なパッケージやライブラリを指定します（今回は未指定）

### プログラム生成

次に、解析データの欄に移動します。
テーブル定義書～共通部品まで、幅広く指定できます。

今回は公式ページのサンプルを一通り落としてきて試しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/50086eb9-aad9-e320-6fb8-ff1cec6ccdc0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/0efb5ccb-492d-e4f7-227a-d7484aa0d3cb.png)

:::note warn
品目在庫管理システム_設計書PDF.zip だけ0kbの破損ファイルなので利用できない点にご注意ください。
:::

---

### DB定義書の指定

中身を見てみると、親の顔より見たExcelのDB定義書でした。もっと親の顔を見るべき。
このようなテーブル定義書の形式が日本では多いと思うのですが、レイアウトの違いがあっても吸収してもらえるのはありがたいですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/b39647af-ef31-dcfa-19d9-627be1cedf2f.png)

これをCodeAGIに取り込みます。
テーブル定義書指定でファイルを取り込み、指定データ確認で取り込んだデータを確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/c2b07a8c-40b3-66ad-3634-f458f2e2d095.png)

---

### 画面定義書の指定

同様に、画面定義書の指定を行います。子供の顔より見た画面定義書ですね。子供いませんが。
このようなフォーマットも日本では多いと思います。**きっちりセル結合もされてました。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/36f33dcd-4465-22b9-f81c-7dbc50533d9e.png)

これもCodeAGIに取り込みます。
いくつかマニュアルで指定できる欄があるので、入力していきます。
これがプロンプトになるんでしょうね。以下は私がよしなに入力したサンプルです。

- 機能名：`仕入情報照会`
- 機能概要：`仕入情報の一覧を表示します。合計金額を集計行に表示します。画面上部には仕入先・仕入担当者・仕入れ日・商品種別・商品名を指定して、テーブルからデータを検索します。`
- 機能種別：`画面`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/83f25312-ca91-b89d-ef00-2f32a11eb488.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/5548c046-c9b0-7b26-cdef-0fc270727fa5.png)

セル結合をものともせず、しっかり取り込んでくれました。既存の設計書を修正することなくそのまま使えるのは、運用コストの軽減にも使えますし、非常に大きなメリットではないでしょうか。

---

### 画面イメージの指定

次に、画面イメージの指定も行います。どの画面と紐付くイメージなのか指定することができます。私はExcelのスクリーンショットをそのまま飲ませました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/6cf08917-8e96-d30e-228a-a0497706625f.png)

:::note info
余談ですが、画像だけを後から差し替えたりも可能です。つまり、打ち合わせ中に急に画面レイアウトが変わったとしても、CodeAGIだけで吸収することができます。優秀ですね。
:::


---

### プログラムの生成

では、プログラムを生成してみましょう。
プログラム生成画面で、プログラム生成ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/542af7ea-2b07-9503-f499-5bdd47147612.png)

すると、数分でプログラムの生成が完了しました。いい感じですね。
今回はPythonのDjangoのコードを生成しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/2052ad62-c153-f23c-1600-e516c67498c8.png)

生成プログラムの確認機能に移動して、出力したいプログラムを選びます。
その後、ファイル出力をクリックすることで生成したコードの出力が可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/7c3c7a68-041c-20fa-3891-2986b59bf210.png)

### 実際に生成されたプログラム

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/8b951fbe-6021-152a-e203-21314bb8da91.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/5000142c-abc5-ea9a-b646-45c659b914f8.png)

---

### テストケース・データ生成

続いて、テストケース・テストデータを生成してみましょう。
テストケース・データ生成画面で、テストケース＆データ生成ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/a35f462c-a154-3447-0db5-5d68229337a5.png)

ものの数分でテストケースとデータが生成されました。先ほどと同様に出力していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/71f2e275-69ce-5efc-ea57-f80376573462.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/906ffbf3-d66a-87e9-934f-804765429e15.png)

嫁の顔より見たテストケースが出力されました。独身ですけどね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/13ba19e4-e76e-d5e9-693c-6a89537cadb1.png)

これだけで、一式のデータが出そろいました。
手順の案内はここまでにして、実際に生成されたコードを確認していきます。

## 生成物

:::note info
本稿はCodeAGIの紹介記事のため、コードの質については深く言及しません。
モデル依存の自動生成が行われていると思うので、ぜひ色々なモデルや入力を試してみてください。
:::

### Python（Django）の場合

実際のコードを見てみます。いい感じにフロントエンドが構成されています。
<details><summary>purchase_information_template.html</summary><div>

```purchase_information_template.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>仕入情報照会</title>
</head>
<body>
    <h1>仕入情報照会</h1>
    <form action="{% url 'purchase-information' %}" method="get">
        <label for="supplier">仕入先：</label>
        <select id="supplier" name="supplier">
            <!-- 仕入先リストはサーバーサイドで生成される想定 -->
        </select>

        <label for="purchase_pic">仕入担当者：</label>
        <select id="purchase_pic" name="purchase_pic">
            <!-- 仕入担当者リストはサーバーサイドで生成される想定 -->
        </select>

        <label for="start_date">仕入開始日：</label>
        <input type="date" id="start_date" name="start_date" value="{{ 当月月初 }}">

        <label for="end_date">仕入終了日：</label>
        <input type="date" id="end_date" name="end_date" value="{{ 当月月末 }}">

        <label for="item_category">商品種別：</label>
        <select id="item_category" name="item_category">
            <!-- 商品種別リストはサーバーサイドで生成される想定 -->
        </select>

        <label for="item_name">商品名：</label>
        <input type="text" id="item_name" name="item_name" maxlength="50">

        <button type="submit">検索</button>
    </form>

    <table>
        <thead>
            <tr>
                <th>№</th>
                <th>商品コード</th>
                <th>商品名</th>
                <th>商品種別</th>
                <th>仕入先</th>
                <th>仕入日</th>
                <th>仕入単価</th>
                <th>仕入数量</th>
                <th>仕入金額</th>
                <th>仕入担当者名</th>
            </tr>
        </thead>
        <tbody>
            <!-- 仕入情報のテーブルデータはサーバーサイドで生成される想定 -->
        </tbody>
    </table>
</body>
</html>
```
</div></details>

バックエンドも想定した通りのコードが自動生成されています。
最も懸念点であったフロントエンドとの対応は、しっかりと対応するように構築されていました。

<details><summary>model.py</summary><div>

```model.py
from django.db import models

class ItemCategory(models.Model):
    """ 商品種別マスタ """
    item_category = models.CharField(max_length=3, primary_key=True, db_column='ITEM_CATEGORY')
    item_category_name = models.CharField(max_length=50, db_column='ITEM_CATEGORY_NAME')
    regist_person = models.CharField(max_length=5, db_column='REGIST_PERSON')
    regist_datetime = models.DateTimeField(db_column='REGIST_DATETIME')
    edit_person = models.CharField(max_length=5, db_column='EDIT_PERSON', null=True)
    edit_datetime = models.DateTimeField(db_column='EDIT_DATETIME', null=True)

    class Meta:
        db_table = 'MST_ITEM_CATEGORY'

class Item(models.Model):
    """ 商品マスタ """
    item_code = models.CharField(max_length=13, primary_key=True, db_column='ITEM_CODE')
    item_name = models.CharField(max_length=100, db_column='ITEM_NAME')
    item_short_name = models.CharField(max_length=50, db_column='ITEM_SHORT_NAME')
    item_category = models.ForeignKey(ItemCategory, on_delete=models.CASCADE, db_column='ITEM_CATEGORY')
    regist_person = models.CharField(max_length=5, db_column='REGIST_PERSON')
    regist_datetime = models.DateTimeField(db_column='REGIST_DATETIME')
    edit_person = models.CharField(max_length=5, db_column='EDIT_PERSON', null=True)
    edit_datetime = models.DateTimeField(db_column='EDIT_DATETIME', null=True)

    class Meta:
        db_table = 'MST_ITEM'

class Person(models.Model):
    """ 担当者マスタ """
    person_code = models.CharField(max_length=5, primary_key=True, db_column='PERSON_CODE')
    person_name = models.CharField(max_length=100, db_column='PERSON_NAME')
    person_division = models.CharField(max_length=50, db_column='PERSON_DIVISION')
    person_phone_no = models.CharField(max_length=15, db_column='PERSON_PHON_NO')
    regist_person = models.CharField(max_length=5, db_column='REGIST_PERSON')
    regist_datetime = models.DateTimeField(db_column='REGIST_DATETIME')
    edit_person = models.CharField(max_length=5, db_column='EDIT_PERSON', null=True)
    edit_datetime = models.DateTimeField(db_column='EDIT_DATETIME', null=True)

    class Meta:
        db_table = 'MST_PERSON'

class Supplier(models.Model):
    """ 仕入先マスタ """
    supplier_code = models.CharField(max_length=4, primary_key=True, db_column='SUPPLIER_CODE')
    supplier_name = models.CharField(max_length=100, db_column='SUPPLIER_NAME')
    supplier_short_name = models.CharField(max_length=50, db_column='SUPPLIER_SHORT_NAME')
    supplier_phone_no = models.CharField(max_length=15, db_column='SUPPLIER_PHONE_NO')
    supplier_pic = models.CharField(max_length=100, db_column='SUPPLIER_PIC')
    regist_person = models.CharField(max_length=5, db_column='REGIST_PERSON')
    regist_datetime = models.DateTimeField(db_column='REGIST_DATETIME')
    edit_person = models.CharField(max_length=5, db_column='EDIT_PERSON', null=True)
    edit_datetime = models.DateTimeField(db_column='EDIT_DATETIME', null=True)

    class Meta:
        db_table = 'MST_SUPPLIER'

class PurchaseInformation(models.Model):
    """ 仕入情報 """
    purchase_no = models.IntegerField(primary_key=True, db_column='PURCHASE_NO')
    purchase_date = models.DateField(db_column='PURCHASE_DATE')
    supplier_code = models.ForeignKey(Supplier, on_delete=models.CASCADE, db_column='SUPPLIER_CODE')
    item_code = models.ForeignKey(Item, on_delete=models.CASCADE, db_column='ITEM_CODE')
    purchase_unit_price = models.DecimalField(max_digits=10, decimal_places=2, db_column='PURCHASE_UNIT_PRICE')
    purchase_quantity = models.IntegerField(db_column='PURCHASE_QUANTITY')
    purchase_pic = models.ForeignKey(Person, on_delete=models.CASCADE, db_column='PURCHASE_PIC')
    regist_person = models.CharField(max_length=5, db_column='REGIST_PERSON')
    regist_datetime = models.DateTimeField(db_column='REGIST_DATETIME')
    edit_person = models.CharField(max_length=5, db_column='EDIT_PERSON', null=True)
    edit_datetime = models.DateTimeField(db_column='EDIT_DATETIME', null=True)

    class Meta:
        db_table = 'PURCHASE_INFORMATION'
```
</div></details>

<details><summary>serializers.py</summary><div>

```serializers.py
from rest_framework import serializers
from .models import Supplier, Person, ItemCategory, Item, PurchaseInformation

class SupplierSerializer(serializers.ModelSerializer):
    """ 仕入先マスタのシリアライザ """
    class Meta:
        model = Supplier
        fields = '__all__'

class PersonSerializer(serializers.ModelSerializer):
    """ 担当者マスタのシリアライザ """
    class Meta:
        model = Person
        fields = '__all__'

class ItemCategorySerializer(serializers.ModelSerializer):
    """ 商品種別マスタのシリアライザ """
    class Meta:
        model = ItemCategory
        fields = '__all__'

class ItemSerializer(serializers.ModelSerializer):
    """ 商品マスタのシリアライザ """
    class Meta:
        model = Item
        fields = '__all__'

class PurchaseInformationSerializer(serializers.ModelSerializer):
    """ 仕入情報のシリアライザ """
    supplier_code = serializers.CharField(source='supplier_code.supplier_short_name')
    item_code = serializers.CharField(source='item_code.item_short_name')
    purchase_pic = serializers.CharField(source='purchase_pic.person_name')

    class Meta:
        model = PurchaseInformation
        fields = ['purchase_no', 'purchase_date', 'supplier_code', 'item_code', 'purchase_unit_price', 'purchase_quantity', 'purchase_pic']
```
</div></details>

<details><summary>urls.py</summary><div>

```urls.py
from django.urls import path
from .views import PurchaseInformationView

urlpatterns = [
    path('purchase-information/', PurchaseInformationView.as_view(), name='purchase-information'),
]
```
</div></details>

<details><summary>views.py</summary><div>

```views.py
from django.shortcuts import render
from rest_framework import generics
from .models import PurchaseInformation
from .serializers import PurchaseInformationSerializer
from django.db.models import Sum, F
from .messages import ERROR_NO_SEARCH_RESULTS, ERROR_SEARCH_DATE_ISSUE, ERROR_MISSING_SEARCH_CRITERIA

class PurchaseInformationView(generics.ListAPIView):
    """ 仕入情報照会ビュー """
    serializer_class = PurchaseInformationSerializer

    def get_queryset(self):
        """
        (comment Start)1-1.本画面の使用権限があるか確認する（共通部品を参照）(comment End)
        検索処理を行い、仕入情報を取得する。
        """
        # 検索条件の取得
        supplier = self.request.query_params.get('supplier', None)
        purchase_pic = self.request.query_params.get('purchase_pic', None)
        start_date = self.request.query_params.get('start_date', None)
        end_date = self.request.query_params.get('end_date', None)
        item_category = self.request.query_params.get('item_category', None)
        item_name = self.request.query_params.get('item_name', None)

        # 検索条件のバリデーション
        if not start_date or not end_date:
            raise ValueError(ERROR_MISSING_SEARCH_CRITERIA)
        if start_date > end_date:
            raise ValueError(ERROR_SEARCH_DATE_ISSUE)

        # クエリセットの構築
        queryset = PurchaseInformation.objects.all()
        if supplier:
            queryset = queryset.filter(supplier_code__supplier_short_name=supplier)
        if purchase_pic:
            queryset = queryset.filter(purchase_pic__person_name=purchase_pic)
        if start_date and end_date:
            queryset = queryset.filter(purchase_date__range=[start_date, end_date])
        if item_category:
            queryset = queryset.filter(item_code__item_category__item_category_name=item_category)
        if item_name:
            queryset = queryset.filter(item_code__item_short_name__icontains=item_name)

        # 検索結果が0件の場合のエラーハンドリング
        if not queryset.exists():
            raise ValueError(ERROR_NO_SEARCH_RESULTS)

        return queryset
```
</div></details>

実際にDjangoのプロジェクトに配置してみたのがこちらです。いくつかエラーは表示されているものの、ファイル自体は問題なく適用できていることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/65426c74-b85e-c6db-375e-5efa5d941aa7.png)

もし、生成されたファイルをどう扱っていいかわからない場合は、ChatGPTに聞いてみれば問題ありません。つまり、 **ほとんど経験がないエンジニアでも、まずCodeAGIでコードを生成して、ChatGPTのアシストの元でシステムの構築ができる**ということです。
後述しますが、最も工数のかかるである「PG補正」まで生成AIに頼ることで、素人エンジニアでも自立して実装を進めることができ、さらなる効率化を図れますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/b1a5ac2e-78fe-371f-c236-3dc754afb990.png)


### C#.NETの場合

参考までに、C#.NETでも同じソースを生成してみました。こちらも、MVCモデルに則ってファイルが構成されていることがわかります。Djangoと違い回想が多いですが、すべて既定のフォルダ構造に従ってファイルが生成されていました。
このように自動でフォルダ構成が組まれていることにより、手動でファイルを再配置する必要がないため、駆け出しエンジニアでも迷わず構築することが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/c9a960cd-8724-181f-2717-9b4dff25a861.png)


## 実際に使ってみた感想

生成されたプログラムは、 **配置すればそのまま実装できるもの** が中心でした。おそらく実際の用途としては、新規でプロジェクトを作成して、そこに配置していく形になります。

もちろん、手で修正する必要があるコードは一定数ありました。そのステップが、先ほどお見せした資料の「PG補正」というステップになるのだと想定されます。
このPG補正の工数を見てもわかる通り、1から構築するよりも相当数の工数を削減することが可能です。「一回の出力で不具合なく動かないと嫌だ！」という声は多くないと思いますので、開発においては有益なシステムだと考えられます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/7981491a-e7ee-17e3-c6b3-86b666fabcc5.png)

CodeAGIの強みは、けして「設計書を入力すればそのまま使えるコードが生成される点」ではありません。
**社内の大量の設計書から仕様を正確に読み込み** 、 **複数ファイルに渡るプログラムコード、及びテストケースとデータが生成できる** ところが、CodeAGIの最も大きな特徴だと思います。

生成されたコードのクオリティは、普段から生成AIに触れておられる皆様ならご理解いただけると思います。今までであれば、これらの作業をすべて対話型のチャットUIで実現しようとすると、トライ＆エラーによる労力が必要でした。 CodeAGIであれば、**自律型エージェントとしてこれらの一連の作業を自動化してもらえる** ことが、非常に魅力的ですね。

## 実際の開発でどのように使えるか

### Excel文化への適応

日本はドキュメント文化ですので、「チケット駆動開発」のようにチケット単位で仕様を変えるような運用ではありません。良くも悪くも、「Excel方眼紙による設計書」が跋扈している文化が根付いています。
2000年代～2010年代に「仕様書が残っていない」という課題提起があちらこちらで起きたため、特に近年では「設計書をしっかりと作成する」「設計書が正義である」という常識が強くなってきたように思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/bdaffb53-586a-f41d-d82a-914656a6e165.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/40acddfd-e532-5f54-9336-d9f00584b81d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/3cf36150-8cb8-a41e-2348-176933cd88ce.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/bd347d0f-ed46-9e3e-bd78-a5490d782b4c.png)

ただ、未だにセル結合が多用されているフォーマットや、各社によって微妙に違うフォーマットが存在しているのも事実です。総務省が出したガイドラインに真っ向から歯向かうようなレイアウトも少なくありません。

統計表における機械判読可能なデータ作成に関する表記方法について - 総務省

https://www.soumu.go.jp/main_content/000723697.pdf

**ドキュメントは度重なる承認フローで綺麗にできたけど、実装の時間が圧迫されてしまった。加えて、案件によってフォーマットもバラバラ** なのがここ数年の傾向だと思います。（私見）
そんな日本文化に対して、「実戦で役に立つ生成AIシステム」として開発されたこのシステムは、現場に導入すればすぐに適用できる **「銀の弾丸」に限りなく近づける仕組み** だと考えられます。

### 仕様変更工数への対応

日本では「ウォーターフォール開発」が主流ではありますが、その実「プロトタイプ開発」になりがちです。どういうことかというと、「顧客は設計段階で完成物をイメージするスキルがない」ためです。
そのため、要件定義を念入りに行い、基本設計で認識を合わせ、詳細設計書で内容を詰めて、コーディングをして成果物をデモしたタイミングで「やはりここを直してほしい」という声が上がってきます。SIer殺しですね。

そのため、ウォーターフォール開発にも関わらず、**いかに顧客の要望を高速に吸収するか**、**イテレーションを高速に回すか**が重要になってきます。その点において、CodeAGIは 仕様変更内容を反映したExcelファイルを取り込むだけで、その変更内容が反映されます。加えて、CodeAGIではファイル単位でコードを出力できるため、仕様変更があった差異ファイルだけ出力できます。これによって、高速で「デモ」→「仕様変更対応」を繰り返すことが可能になると感じました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/0cef4d10-8c8b-c391-691b-2a99fa83e077.png)

### 新入社員のOJT用ツールとして活用

現場に入ったばかりの新入社員は、まだコードの書き方すらわからないことがほとんどです。そのようなときは、「完成したコード」と「仕様書」を見比べて、どのコードがどのような作業をしているかを地道に確認して学んでいくことが多いと思います。
その点、CodeAGIがあれば、「開発業務をこなしながら自走して学ぶことができる」点が強みだと思います。

「AIが仕事を奪う」とよく言われていますが、その実「コードの書き方はAIの補助によって効率化できる」、一方で「そのコードが顧客のニーズに合っているか確認する必要がある」「最後のコードの微調整は人間が行う必要がある」ため、完全な自動化は難しいと言われています。

言語ごとのコードの書き方やファイルの配置はChatGPTなどでカバーすることができます。カバーできない点が人間の仕事です。CodeAGIにおいてもそこは変わらず、残る作業は主にその2点です。そのためCodeAGIの利用は、生成AI時代のエンジニアの育成方法として最適化された形なのではないかと感じた次第です。

## まとめ

本日はCodeAGIについてレビューさせて頂きましたが、楽しんで頂けたでしょうか？
生成AIは既に素晴らしいコードを書けるレベルまで昇華されました。今後生成AIに求められているのは、 **人間の意図・要望（設計書）を正確に汲み取り、生成したコードを適切に組み合わせて、そのまま使えるものを生成する能力** だと思われます。それは、Claude 3.5 Sonnetの登場で、みなさまが最も実感されたことではないでしょうか。

CodeAGIは、実運用に寄り添ったアプリケーション開発向けの生成AI自律型エージェントです。ご興味があれば、ぜひ社内のファイルを用いてお試しくださいませ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419037/0e686acc-20f4-9423-014b-1e7e2489817a.png)

最後までご覧いただき、ありがとうございました。

## 最後に
＊本稿は、**個人の見解に基づいた内容**であり、**所属する会社の公式見解ではありません**。また、**いかなる保証を与えるものでもありません**。正式な情報は、各製品の販売元にご確認ください。