GPTs Actions Schemaの簡単構築術

## はじめに


GPTs Actionsの構築は、今日のデジタル世界における重要なスキルの一つです。特に、GPTsに特化した「ActionsGPT」は、この分野での作業を劇的に簡素化します。この記事では、GPTs Actionsを構築するための簡単な方法と、ActionsGPTの利用方法を詳しく解説します。

---

この辺りのGPTsもこちらのワークフローで作成してます

https://hamaruki.com/how-to-collaborate-with-line-bot-messaging-api-using-gpts-actions/

https://hamaruki.com/create-with-google-apps-script-gpts-actions-api-that-returns-the-dish-name-from-the-dish-number/

## GPTs Actions Schemaの構築方法

GPTs Actions Schemaを構築する際、まず理解するべきは、ActionsGPTがどのようにしてこのプロセスを容易にするかという点です。このツールは、GPTs Actionsの内容を深く学習しており、ユーザーが参考サイトのSchemaを提供するだけで、高精度なSchemaを生成できます。

## SchemaからGASへの変換

GPTs Actionsを利用する際の一つの利点は、SchemaからGoogle Apps Script（GAS）を作成できることです。これにより、ユーザーは独自のスクリプトを書くことなく、効率的にGPTs Actionsを実装できます。

## GASからSchemaの生成

逆に、既存のGASを持っている場合、ActionsGPTはこれを分析し、適切なSchemaを生成することが可能です。これにより、GPTs Actionsの構築プロセスがさらにスムーズになります。

### たたき台の作成

#### Person:

- 

```javascript
function myFunction() {
  let response = UrlFetchApp.fetch("https://arxiv.org/list/cs/new");
  let content = response.getContentText("utf-8");

  var items = Parser.data(content).from('<dt>').to('</dd>').iterate();

  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();

  // シートの内容をクリア
  sheet.clear();

  // 列名を設定
  sheet.getRange(1, 1).setValue("Title");
  sheet.getRange(1, 2).setValue("Abstract");
  sheet.getRange(1, 3).setValue("Authors");
  sheet.getRange(1, 4).setValue("Paper URL");
  sheet.getRange(1, 5).setValue("GitHub URL");
  sheet.getRange(1, 6).setValue("Full Text");

  items.forEach(function(item, index) {
    // タイトルの抽出
    // ...

    // Googleシートに書き込む
    // 2行目からデータを書き込む（1行目は列名）
    sheet.getRange(index + 2, 1).setValue(title);
    sheet.getRange(index + 2, 2).setValue(abstract);
    sheet.getRange(index + 2, 3).setValue(authors);
    sheet.getRange(index + 2, 4).setValue(paperUrl);
    sheet.getRange(index + 2, 5).setValue(githubUrl);
    sheet.getRange(index + 2, 6).setValue(item); // 全文データ
  });
}
```

上記の処理を踏まえて、下記のIDを入れると検索するコードから、任意の数字を受け取ったら、上からその数字の論文の数の内容を返すようにして

```javascript
function doGet(e) {
  // リクエストからパラメータを取得
  console.log("start GPTs Custom Actions API test");
  console.log("e: " + JSON.stringify(e));
  var searchQuery = e.parameter.id;
  console.log("e.parameter.id: " + e.parameter.id);

  // 4桁の数字かどうかをチェック
  if (!searchQuery || !/^\d{4}$/.test(searchQuery)) {
    console.log("bad format: " + searchQuery);
    return ContentService.createTextOutput(
      JSON.stringify({ "error": "Invalid request. Please provide a 4-digit number." })
    ).setMimeType(ContentService.MimeType.JSON);
  }

  // スプレッドシートの準備
  var sheet = SpreadsheetApp.openById('17WqvBLUb1VTgIjFl4LG6kYzepQAeqk1y2hVVoKglnOc').getSheetByName('シート1');
  var data = sheet.getDataRange().getValues();
  console.log("format OK");

  // スプレッドシートを検索
  for (var i = 1; i < data.length; i++) {  // 2行目から開始
    if (data[i][0].toString() === searchQuery) {
      console.log("hit: " + i);
      console.log("Food Name: " + data[i][1]);
      // 見つかった場合、JSONとして返す
      return ContentService.createTextOutput(
        JSON.stringify({ "Food Name": data[i][1] })
      ).setMimeType(ContentService.MimeType.JSON);
    }
  }
  console.log("not found");
  // 一致するデータが見つからない場合
  return ContentService.createTextOutput(
    JSON.stringify({ "error": "No data found for the provided number." })
  ).setMimeType(ContentService.MimeType.JSON);
}
```

#### ChatGPT: 
- このスクリプトの修正を行うには、以下のステップに従います。 
1. **パラメータの解釈** :
`doGet` 関数で、クエリパラメータとして `id` を受け取ります。この `id` パラメータは、スプレッドシートから取得したい論文の数を示します。 
2. **バリデーションの変更** :
現在のバリデーションでは4桁の数字のみを受け付けていますが、これを任意の正の整数に変更します。 
3. **指定された数の論文を返す** :
スプレッドシートから、指定された数の論文を取得し、それらをJSON形式で返します。

修正後のコードは次のようになります。

```javascript
function doGet(e) {
  // リクエストからパラメータを取得
  console.log("start GPTs Custom Actions API test");
  console.log("e: " + JSON.stringify(e));
  var numberOfPapers = e.parameter.id;
  console.log("e.parameter.id: " + e.parameter.id);

  // パラメータが正の整数かどうかをチェック
  if (!numberOfPapers || !/^\d+$/.test(numberOfPapers)) {
    console.log("bad format: " + numberOfPapers);
    return ContentService.createTextOutput(
      JSON.stringify({ "error": "Invalid request. Please provide a positive integer." })
    ).setMimeType(ContentService.MimeType.JSON);
  }

  // スプレッドシートの準備
  var sheet = SpreadsheetApp.openById('17WqvBLUb1VTgIjFl4LG6kYzepQAeqk1y2hVVoKglnOc').getSheetByName('シート1');
  var data = sheet.getDataRange().getValues();
  console.log("format OK");

  // 指定された数の論文を返す
  var papers = [];
  for (var i = 1; i <= Math.min(data.length - 1, Number(numberOfPapers)); i++) {
    var paperData = {
      "Title": data[i][0],
      "Abstract": data[i][1],
      "Authors": data[i][2],
      "Paper URL": data[i][3],
      "GitHub URL": data[i][4],
      "Full Text": data[i][5]
    };
    papers.push(paperData);
  }

  // 結果をJSONとして返す
  return ContentService.createTextOutput(
    JSON.stringify(papers)
  ).setMimeType(ContentService.MimeType.JSON);
}
```



この修正により、`id` パラメータに指定された数だけ、スプレッドシート上の論文情報を返すようになります。パラメータが正の整数でない場合は、適切なエラーメッセージが返されます。

### スクリプトの微調整

#### Person: 
- Full Textはデバッグ用なので不要です。
上記の最新論文を取得するコードをもとに、下記のコードを修正して

```yaml
{
  "openapi": "3.1.0",
  "info": {
    "title": "Get name data",
    "description": "Get lastname and firstname by id",
    "version": "v1.0.0"
  },
  "servers": [
    {
      "url": "https://script.google.com"
    }
  ],
  "paths": {
    "/macros/s/AKfycbyRbbQjj7A0gUGXlIzkhHcn1ohpX4KlT6D61Pf_L1YrzDLJN-4YCEVLQyS5C29OMIfO/exec": {
      "get": {
        "description": "Get lastname and firstname by id",
        "operationId": "GetNameByid",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "description": "ID No.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "deprecated": false
      }
    }
  },
  "components": {
    "schemas": {
      "NameResponse": {
        "type": "object",
        "properties": {
          "Name": {
            "type": "string"
          }
        }
      }
    }
  }
}

```

#### ChatGPT: 
- このスクリプトは、OpenAPI 3.1.0 スペックを使用してAPIの仕様を定義しています。この仕様を修正して、最新の論文を取得する機能を反映させるには、以下のステップを実行します。 
1. **エンドポイントの説明を更新する** :
現在の説明は「IDによって姓と名を取得する」となっていますが、これを「指定された数の最新論文を取得する」という説明に変更します。 
2. **パラメータの定義を更新する** :
現在の`id`パラメータは文字列型として定義されていますが、これを正の整数を受け入れるように変更します。 
3. **レスポンスのスキーマを更新する** :
現在のスキーマは単一の名前を返すように設定されていますが、これを論文のリストを返すように変更します。

修正後のOpenAPIスペックは以下のようになります。

```yaml
openapi: "3.1.0"
info:
  title: "Get latest papers"
  description: "Get a list of the latest papers by the specified number"
  version: "v1.0.0"
servers:
  - url: "https://script.google.com"
paths:
  /macros/s/AKfycbyRbbQjj7A0gUGXlIzkhHcn1ohpX4KlT6D61Pf_L1YrzDLJN-4YCEVLQyS5C29OMIfO/exec:
    get:
      description: "Get a list of the latest papers by the specified number"
      operationId: "GetLatestPapers"
      parameters:
        - name: "id"
          in: "query"
          description: "Number of papers to retrieve"
          required: true
          schema:
            type: "integer"
            format: "int32"
            minimum: 1
      deprecated: false
components:
  schemas:
    PapersResponse:
      type: "object"
      properties:
        Papers:
          type: "array"
          items:
            type: "object"
            properties:
              Title:
                type: "string"
              Abstract:
                type: "string"
              Authors:
                type: "string"
              PaperURL:
                type: "string"
              GitHubURL:
                type: "string"
```



この変更により、APIは指定された数の最新論文を取得し、そのタイトル、アブストラクト、著者、論文URL、GitHub URLを含むリストを返すようになります。また、パラメータ`id`は正の整数として定義されており、少なくとも1の値が必要です。



## ドキュメントからSchemaの生成

### ベースとなるPOSTリクエストの生成

まず、POSTリクエストを実施するサンプルのSchemaを生成してもらいます。


#### Person: 

- POSTする例を日本語でください

#### ChatGPT: 
- もちろんです。OpenAPI 3.0の仕様を使って、POSTリクエストの例を日本語で説明します。ここでは、ユーザーを作成するためのAPIエンドポイントを想定しています。このエンドポイントは、ユーザー名とパスワードをJSON形式で受け取り、新しいユーザーを作成します。

```yaml
openapi: 3.0.0
info:
  title: ユーザー管理API
  description: ユーザー情報を管理するためのAPIです。
  version: 1.0.0
servers:
  - url: http://api.example.com/v1
    description: 本番サーバー
paths:
  /users:
    post:
      operationId: createUser
      summary: ユーザーを作成します。
      description: 新しいユーザーを作成するためのエンドポイントです。
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                  description: ユーザー名
                password:
                  type: string
                  description: パスワード
      responses:
        '201':
          description: ユーザー作成成功
        '400':
          description: 不正なリクエスト
```



この仕様では、`/users` パスに対してPOSTリクエストを送ることでユーザーを作成できます。リクエストボディには `username` と `password` が必要です。このAPIは成功時にステータスコード201を返し、不正なリクエストの場合は400を返します。


このような仕様では、必要なパラメータやリクエストの形式が明確になり、ユーザーは簡単にAPIを利用できます。

### LINE Messaging API Schemaの生成

次に、ベースとなるPOST Schemaを参考にLINE Messaging APIのドキュメントを考慮したSchemaを生成してもらいます。

https://developers.line.biz/ja/reference/messaging-api/#send-broadcast-message


#### Person: 
- 下記の情報を用いてGPTｓからlineに情報を展開して

```bash
POST https://api.line.me/v2/bot/message/broadcast

curl -v -X POST https://api.line.me/v2/bot/message/broadcast \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {channel access token}' \
-H 'X-Line-Retry-Key: {UUID}' \
-d '{
    "messages":[
        {
            "type":"text",
            "text":"Hello, world1"
        },
        {
            "type":"text",
            "text":"Hello, world2"
        }
    ]
}'
```

#### ChatGPT: 
- 以下は、提供された情報を基に、LINE Messaging APIの `broadcast` エンドポイントに対するOpenAPI 3.0仕様を作成したものです。この仕様は、指定したメッセージをLINEのボットから全ユーザーにブロードキャストするために使用されます。

```yaml
openapi: 3.0.0
info:
  title: LINE Messaging API
  description: LINE Messaging APIを通じてメッセージを送信する。
  version: 1.0.0
servers:
  - url: https://api.line.me/v2/bot
    description: LINE Messaging APIサーバー
paths:
  /message/broadcast:
    post:
      operationId: broadcastMessage
      summary: メッセージを全ユーザーにブロードキャストする。
      description: LINEボットが指定したメッセージを全ユーザーにブロードキャストします。
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                messages:
                  type: array
                  description: 送信するメッセージの配列。
                  items:
                    type: object
                    properties:
                      type:
                        type: string
                        description: メッセージのタイプ。
                      text:
                        type: string
                        description: 送信するテキストメッセージ。
      responses:
        '200':
          description: メッセージ送信成功
        '400':
          description: 不正なリクエスト
      security:
        - lineAuth:
            - channelAccessToken
securitySchemes:
  lineAuth:
    type: http
    scheme: bearer
    bearerFormat: JWT
```



この仕様には、リクエストボディでメッセージのタイプとテキストを指定する必要があります。また、セキュリティスキームとしてBearer認証を使用し、`Authorization` ヘッダーにチャネルアクセストークンを含める必要があります。このエンドポイントは、正常にメッセージが送信された場合にステータスコード200を返し、不正なリクエストの場合は400を返します。




この仕様では、メッセージのタイプやテキスト、セキュリティスキームなどが定義されており、ユーザーはLINEのボットから効果的にメッセージを送信できます。

**結論** 

GPTs Actionsの構築は、ActionsGPTのようなツールを活用することで、非常に簡単かつ効率的になります。この記事で紹介したような例は、GPTs Actionsの構築を始める際の素晴らしい出発点となるでしょう。