【ChatGPT】コピペでスプレッドシートの設計書からswaggerコードを生成する

# この記事でできること
スプレッドシートのコピペだけでswaggerのopenapi.yamlのコードを出力できます

![api-target-spreadsheet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784710/a1104be1-29c7-6e75-8a2b-06d69bc78efb.png)

**↓** (コード生成)

![chatgpt-gen.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784710/aa58dc3c-c4dc-548d-98e7-2ecb1acbda43.png)


# はじめに
プログラムの設計書をスプレッドシートなどで書いている現場では、コードを起こすときに変数名をポチポチ入力するといった単純作業が増えませんか？

そんなとき「ChatGPTが選択範囲だけ自動でコードを生成してくれたらいいのになぁ...」と思ったのでプロンプトで出力できないかと試みてみました。

今回は**シートのコピペだけ**で、API設計書からSwaggerのopenapi.yamlのコードを生成してみます。

# Few-Shot プロンプト
プロンプトのテクニックの中に、**Few-Shotプロンプト**という手法があります。
質問と回答の例を与え、期待するフォーマットで回答を出力させる方法です。

参考: https://www.promptingguide.ai/jp/techniques/fewshot

**例:**
_プロンプト_
```
世界の都市に関する質問に答えてください。
入出力の例を与えます。

####
入力/出力

日本/東京
イギリス/ロンドン
フランス/パリ
####

以下の入力に答えてください。

アメリカ
```
_回答_
```
ワシントンDC
```

このテクニックを用いることで、構造化データを他のフォーマットに変換できるのではないかと考えました。

# やってみる
動画投稿サイトを作るシチュエーションを想定してAPIを作成してみます。
例として「ユーザー登録API」を事前に作成し、\
生成対象として「動画登録API」の設計書を与えてみましょう。

## 1.プロンプトに与える例の準備
Few-Shotの例として与える、API設計書とコードの対応を１つ準備します。
* スプレッドシートのAPI設計書
![api-sample-spreadsheet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784710/b0931943-e652-5874-e566-9cfdec67fdc8.png)

* 対応するopenapi.yamlのコード
```yaml:openapi.yaml
paths: 
  /user/regist:
    post:
      summary: ユーザー登録API
      description: 新規ユーザーを登録する
      requestBody:
        $ref: '#/components/requestBodies/UserRegistRequestBody'
      responses:
        '200':
          description: 成功レスポンス
        '400':
          $ref: '#/components/responses/4xxClient'

components:
  requestBodies:
    UserRegistRequestBody:
      description: ユーザー登録APIリクエスト
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/UserRegistRequest'

  schemas:
    UserRegistRequest:
      type: object
      properties:
        name:
          description: ユーザー名
          type: string
        email:
          description: メールアドレス
          type: string
        videos:
          description: 動画リスト
          type: array
          items:
            $ref: '#/components/schemas/Video'

    Video:
      type: object
      properties:
        title:
          description: タイトル
          type: string
        comments:
          description: コメント
          type: array
          items:
            $ref: '#/components/schemas/Comment'
          nullable: true

    Comment:
      type: object
      properties:
        userId:
          description: 投稿したユーザーID
          type: integer
          format: int64
        text:
          description: コメント内容
          type: string


```

## 2.コード生成させる設計書
それでは、コード生成してほしい設計書を用意しましょう。
今回は、以下のような「動画登録API」をサンプルとして作成しました。
![api-target-spreadsheet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784710/a1104be1-29c7-6e75-8a2b-06d69bc78efb.png)


## 3.プロンプト
まず、今回仕様するプロンプトのテンプレートはこちらです。

```
次のデータ構造を例に従ってyaml形式のデータを出力してください。

例のインプットは次の表形式のデータです。

####
(例のスプレッドシートをコピペ)
####

この例のアウトプットは以下のようになります。

####
(例のopenapi.yamlをコピペ)
####

それでは、次の表形式のデータを例にしたがってyamlデータに変換してください
インプットは以下のデータです

####
(出力したいAPIのスプレッドシートをコピペ)
####
```

1.と2.の情報を `####` で囲われた部分に追加していきます。
画像のようにAPI名、レスポンス型などを含む部分を範囲選択してコピペしましょう。

![api-sample-area.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784710/4371723f-5e2f-11fa-0d36-907e207a7041.png)


実際にChatGPTに投げるプロンプトは以下のようになります。

```
次のデータ構造を例に従ってyaml形式のデータを出力してください。

例のインプットは次の表形式のデータです。

####
API名	ユーザー登録API					
概要	新規ユーザーを登録する					
						
リクエスト						
メソッド	POST					
URI	/user/regist					
データ形式	JSON					
header						
						
						
body				型	必須	説明
name				string	y	ユーザー名
email				string	y	メールアドレス
videos				List<Video>	y	動画リスト
						
型情報	変数名			型	必須	説明
Video						
	title			string	y	タイトル
	comments			List<Comment>		コメント
						
型情報	変数名			型	必須	説明
Comment						
	userId			number	y	投稿したユーザーID
	text			string	y	コメント内容
####

この例のアウトプットは以下のようになります。

####
paths: 
  /user/regist:
    post:
      summary: ユーザー登録API
      description: 新規ユーザーを登録する
      requestBody:
        $ref: '#/components/requestBodies/UserRegistRequestBody'
      responses:
        '200':
          description: 成功レスポンス
        '400':
          $ref: '#/components/responses/4xxClient'

components:
  requestBodies:
    UserRegistRequestBody:
      description: ユーザー登録APIリクエスト
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/UserRegistRequest'

  schemas:
    UserRegistRequest:
      type: object
      properties:
        name:
          description: ユーザー名
          type: string
        email:
          description: メールアドレス
          type: string
        videos:
          description: 動画リスト
          type: array
          items:
            $ref: '#/components/schemas/Video'

    Video:
      type: object
      properties:
        title:
          description: タイトル
          type: string
        comments:
          description: コメント
          type: array
          items:
            $ref: '#/components/schemas/Comment'
          nullable: true

    Comment:
      type: object
      properties:
        userId:
          description: 投稿したユーザーID
          type: integer
          format: int64
        text:
          description: コメント内容
          type: string
####

それでは、次の表形式のデータを例にしたがってyamlデータに変換してください
インプットは以下のデータです

####
API名	動画登録API					
概要	新規動画を登録する					
						
リクエスト						
メソッド	POST					
URI	/videos/upload					
データ形式	JSON					
header						
						
						
body				型	必須	説明
title				string	y	動画タイトル
url				stirng	y	動画のURL
tags				List<Tag>	y	タグ一覧
comments				List<Comment>	y	事前に登録するコメント
						
型情報	変数名			型	必須	説明
Tag						
	tagId			number	y	タグID
	text			string	y	タグのテキスト
						
型情報	変数名			型	必須	説明
Comment						
	userId			number	y	投稿したユーザーID
	text			string	y	コメント内容
####
```

## 実行結果
次のような回答が生成されました。

> 以下は、提供された表形式のデータをもとに作成したYAML形式のデータです。
> 
> ```yaml
> paths:
>   /videos/upload:
>     post:
>       summary: 動画登録API
>       description: 新規動画を登録する
>       requestBody:
>         $ref: '#/components/requestBodies/VideoUploadRequestBody'
>       responses:
>         '200':
>           description: 成功レスポンス
>         '400':
>           $ref: '#/components/responses/4xxClient'
> 
> components:
>   requestBodies:
>     VideoUploadRequestBody:
>       description: 動画登録APIリクエスト
>       required: true
>       content:
>         application/json:
>           schema:
>             $ref: '#/components/schemas/VideoUploadRequest'
> 
>   schemas:
>     VideoUploadRequest:
>       type: object
>       properties:
>         title:
>           description: 動画タイトル
>           type: string
>         url:
>           description: 動画のURL
>           type: string
>         tags:
>           description: タグ一覧
>           type: array
>           items:
>             $ref: '#/components/schemas/Tag'
>         comments:
>           description: 事前に登録するコメント
>           type: array
>           items:
>             $ref: '#/components/schemas/Comment'
> 
>     Tag:
>       type: object
>       properties:
>         tagId:
>           description: タグID
>           type: number
>           format: int64
>         text:
>           description: タグのテキスト
>           type: string
> 
>     Comment:
>       type: object
>       properties:
>         userId:
>           description: 投稿したユーザーID
>           type: number
>           format: int64
>         text:
>           description: コメント内容
>           type: string
> ```
> 
> このYAMLデータは、提供された表形式のデータに基づいて、OpenAPI 3.0の形式に準拠したものです。各部分がパス、リクエストボディ、レスポンスなどに分かれており、型情報も適切に記述されています。

スプレッドシートのコピペから、見事にopenapi.yamlのフォーマットに変換されました！
`Tag`,`Comment`などのネストしている部分や、多少スプレッドシートの行数が増えても対応されているのが生成AIの素晴らしさだと思います。

## おわりに
スプレッドシートを範囲選択しコピペすることでAPI設計書からopenapi.yamlの一部を生成することができました。
これはFew-Shotプロンプトを活用した一例であり、他のいろいろなシチュエーションに利用できる手法だと思います。
「フォーマットは決まってるのに手作業は面倒くさいな...」というときに使っていきたいですね。