【開発者向け】これさえ読めばOK!ChatGPTプラグインの作り方
ChatGPTプラグインの開発方法がOpenAI社からついに公開されましたね!
そこで、この記事では、公開された開発方法を参考に、ChatGPTプラグインの作り方を開発者向けにわかりやすく解説します。
実装手順、それぞれの工程での注意点などを詳しく説明しますので、これさえ読めばあなたもChatGPTプラグインを自信を持って作れるようになりますよ。
これからChatGPTのプラグインの開発を考えている人はぜひ参考にしてみてください
実際に開発される時は、以下のOpenAI社から公開されているガイドラインも併せてお読みください。
おすすめのプラグインについては以下の記事で紹介しているので、便利なプラグインを使うことで生産性を上げたい人はぜひこちらも参考にしてみてください。
ChatGPT プラグインとは
ChatGPTプラグインは、ChatGPTをサードパーティのアプリケーションと連携させるツールです。
これは、GoogleスプレッドシートのアドオンやGoogle Chromeの拡張機能と同様に、公式だけでなく第三者の開発者が作成した機能をChatGPTに追加することで機能を拡充できるものとなっています。
具体的には、プラグインを利用することで、ChatGPTに以下のような機能を追加できるようになります。
- リアルタイムの情報を取得:スポーツのスコアや株価、最新のニュースなどを確認
- ナレッジベースの情報を取得:企業の文書や個人のメモなどを閲覧
- ユーザーの代わりにアクションを実行:フライトの予約や食事の注文などを行う
日本の企業の中にも、すでにこのプラグインを開発しているところがあります。例えば、食べログがその一つです。
食べログのプラグインをChatGPTで有効にすることで、食べログでネット予約が可能な店舗の空席情報を、指定した条件に合わせて簡単に検索できるようになります。
ChatGPTプラグインの開発から公開までの流れ
ChatGPTプラグインの開発から公開までは以下の流れで行う必要があります。
プラグイン作成には、プラグインの情報(名前、ロゴ等)、必要な認証詳細(認証タイプ、OAuth URL等)、公開したいエンドポイントのOpenAPIスペックを含むマニフェストファイルを作成し、特定のURLでホストする必要があります。
プラグインの説明、APIリクエスト、APIレスポンスは全てChatGPTとの対話に挿入され、これはモデルのコンテキスト制限に影響します。
ChatGPTのUIでプラグインを登録します。プラグインモデルをドロップダウンから選択し、「プラグイン」、「プラグインストア」を選び、「未検証のプラグインをインストール」または「自分のプラグインを開発」をクリックします。
認証が必要な場合、OAuth 2のclient_idとclient_secret、またはAPIキーを指定します。
ユーザーはChatGPT上で手動でプラグインを有効化することで利用できるようになります。
認証が必要な場合、ユーザーはOAuth経由でプラグインにリダイレクトされ、新規アカウントの作成も可能です。
OpenAIはユーザーが見えない形でChatGPTにプラグインの要約を提供し、ユーザーが関連する質問をした際、モデルはAPIコールを使ってプラグインから情報を取得できます。
この結果はユーザーへの応答に反映され、APIから返されるリンクはリッチプレビューとして表示されます。これらのリンクはOpenGraphプロトコルを用いて各種情報を抽出します。
また、モデルはAPIからの画像URLなどのマークダウンを出力し、それはChatGPT UIでレンダリングされます。
ChatGPTプラグインの具体的な作り方
プラグインの作成は、3つのステップで行います
- APIを構築する
- OpenAPI yamlまたはJSONフォーマットでAPIをドキュメント化する。
- プラグインの関連するメタデータを定義するJSONマニフェストファイルを作成する。
プラグインマニフェストの基本構成
プラグインはai-plugin.jsonというAPIのドメイン(例:https://example.com)でホストされた設定ファイルが必要です。
ChatGPTがプラグインをインストールするとき、バックエンドは/.well-known/ai-plugin.jsonというパスでこのファイルを探すので、このファイルが存在しないと、プラグインはインストールできません。
開発環境ではHTTPを使ってもよいですが、リモートサーバーではHTTPSが必須となります。
必要なai-plugin.json
ファイルの最小限の定義は以下の通りです。
1{
2 "schema_version": "v1",
3 "name_for_human": "TODO Plugin",
4 "name_for_model": "todo",
5 "description_for_human": "Plugin for managing a TODO list. You can add, remove and view your TODOs.",
6 "description_for_model": "Plugin for managing a TODO list. You can add, remove and view your TODOs.",
7 "auth": {
8 "type": "none"
9 },
10 "api": {
11 "type": "openapi",
12 "url": "http://localhost:3333/openapi.yaml",
13 "is_user_authenticated": false
14 },
15 "logo_url": "http://localhost:3333/logo.png",
16 "contact_email": "support@example.com",
17 "legal_info_url": "http://www.example.com/legal"
18}
設定可能なオプション
以下に、プラグインファイルの全ての可能なオプションについて、表形式でまとめます
これらのフィールドを適切に設定することで、プラグインの振る舞いと機能が決定されます。
フィールド | タイプ | 内容・オプション | 必須 |
---|---|---|---|
schema_version | 文字列 | マニフェストスキーマのバージョン | ✅ |
name_for_model | 文字列 | モデルがプラグインをターゲットにする際に使用する名前(スペース不可、文字と数字のみ)。50文字以内。 | ✅ |
name_for_human | 文字列 | 人間が読める名前、例えば会社名全体など。20文字以内。 | ✅ |
description_for_model | 文字列 | モデルに適した説明(トークンコンテキストの長さを考慮したり、プラグインのプロンプトを改善するためのキーワードを使用するなど)。8000文字以内。 | ✅ |
description_for_human | 文字列 | プラグインの人間が読める説明。100文字以内。 | ✅ |
auth | ManifestAuth | 認証スキーマ | ✅ |
api | オブジェクト | APIの仕様 | ✅ |
logo_url | 文字列 | ロゴを取得するためのURL。推奨サイズ:512×512。透過背景対応。 | ✅ |
contact_email | 文字列 | 安全性/モデレーション、サポート、非活性化のためのメール連絡先 | ✅ |
legal_info_url | 文字列 | プラグイン情報を閲覧するためのリダイレクトURL | ✅ |
HttpAuthorizationType | HttpAuthorizationType | “bearer”または”basic” | ✅ |
ManifestAuthType | ManifestAuthType | “none”, “user_http”, “service_http”, “oauth” のいずれか | – |
BaseManifestAuth | BaseManifestAuth | type: ManifestAuthType; instructions: string; | – |
ManifestNoAuth | ManifestNoAuth | 認証不要: BaseManifestAuth & { type: ‘none’, } | – |
ManifestAuth | ManifestAuth | ManifestNoAuth, ManifestServiceHttpAuth, ManifestUserHttpAuth, ManifestOAuthAuth のいずれか | – |
OpenAPIドキュメントの作成
OpenAPI仕様書の作成はAPIとChatGPTとのインターフェースを定義する重要なステップです。
ChatGPTは、OpenAPI仕様書とマニフェストファイルに記載された情報だけを理解するため、大規模なAPIでも、必要な機能だけをモデルに公開できます。
たとえば、ソーシャルメディアAPIを持つ場合、モデルにGETリクエストを使ってコンテンツを取得させ、スパムを防ぐためにコメント投稿機能を無効にすることができます
「OpenAPIドキュメント」の基本構成は、次のとおりです。
1openapi: 3.0.1
2info:
3 title: TODO Plugin
4 description: A plugin that allows the user to create and manage a TODO list using ChatGPT.
5 version: 'v1'
6servers:
7 - url: http://localhost:3333
8paths:
9 /todos:
10 get:
11 operationId: getTodos
12 summary: Get the list of todos
13 responses:
14 "200":
15 description: OK
16 content:
17 application/json:
18 schema:
19 $ref: '#/components/schemas/getTodosResponse'
20components:
21 schemas:
22 getTodosResponse:
23 type: object
24 properties:
25 todos:
26 type: array
27 items:
28 type: string
29 description: The list of todos.
OpenAPI仕様書の作成は、仕様バージョン、タイトル、説明、バージョン番号の定義から始まります。
ChatGPTがクエリを実行する際、ユーザーのクエリにプラグインが適合するかを判断するために、情報セクションで定義された説明を確認します。
OpenAPIの仕様では、各APIエンドポイントの説明/概要と各APIパラメータの説明は200文字以内に制限されています。この例ではローカルで実行しているため、サーバーはlocalhostのURLを指すよう設定します。
プラグインの実行
API、マニフェストファイル、OpenAPI仕様書が整備されたら、ChatGPTのユーザーインターフェースを通じてプラグインを接続できます。
プラグインは、ローカルの開発環境かリモートサーバーで稼働している場合があります。
ローカルでAPIが稼働している場合、プラグインインターフェースはあなたのlocalhostサーバーを指すように設定できます。
ChatGPTでプラグインを接続するには、「独自のプラグインを開発」を選択し、localhostとポート番号(例:localhost:3333)を入力します。ただし、現在はlocalhostでの開発においては認証タイプ「none」のみがサポートされています。
もしプラグインがリモートサーバー上で動作している場合、「独自のプラグインを開発」を選択して設定した後、「未検証のプラグインをインストール」を選び、自己インストールします。
プラグインのマニフェストファイルを yourdomain.com/.well-known/ パスに追加し、APIのテストが可能です。
ただし、マニフェストファイルに変更を加えた場合は、公開サイトに新たな変更をデプロイする必要があり、これは時間がかかるかもしれません。
そのような場合は、APIのプロキシとしてローカルサーバーを設定することを推奨します。これにより、OpenAPI仕様書とマニフェストファイルへの変更を迅速に試作することが可能となります。
以下のPythonコードは、公開するAPIの簡単なプロキシを設定する方法の例です。
1import requests
2import os
3
4import yaml
5from flask import Flask, jsonify, Response, request, send_from_directory
6from flask_cors import CORS
7
8app = Flask(__name__)
9
10PORT = 3333
11
12# Note: Setting CORS to allow chat.openapi.com is required for ChatGPT to access your plugin
13CORS(app, origins=[f"http://localhost:{PORT}", "https://chat.openai.com"])
14
15api_url = 'https://example.com'
16
17
18@app.route('/.well-known/ai-plugin.json')
19def serve_manifest():
20 return send_from_directory(os.path.dirname(__file__), 'ai-plugin.json')
21
22
23@app.route('/openapi.yaml')
24def serve_openapi_yaml():
25 with open(os.path.join(os.path.dirname(__file__), 'openapi.yaml'), 'r') as f:
26 yaml_data = f.read()
27 yaml_data = yaml.load(yaml_data, Loader=yaml.FullLoader)
28 return jsonify(yaml_data)
29
30
31@app.route('/openapi.json')
32def serve_openapi_json():
33 return send_from_directory(os.path.dirname(__file__), 'openapi.json')
34
35
36@app.route('/<path:path>', methods=['GET', 'POST'])
37def wrapper(path):
38
39 headers = {
40 'Content-Type': 'application/json',
41 }
42
43 url = f'{api_url}/{path}'
44 print(f'Forwarding call: {request.method} {path} -> {url}')
45
46 if request.method == 'GET':
47 response = requests.get(url, headers=headers, params=request.args)
48 elif request.method == 'POST':
49 print(request.headers)
50 response = requests.post(url, headers=headers, params=request.args, json=request.json)
51 else:
52 raise NotImplementedError(f'Method {request.method} not implemented in wrapper for {path=}')
53 return response.content
54
55
56if __name__ == '__main__':
57 app.run(port=PORT)
ディスクリプションの作成
ユーザーがプラグインに関連するクエリを行うと、モデルはOpenAPI仕様のエンドポイント説明とマニフェストファイルのdescription_for_modelを確認します。
そのため、最適なプロンプトと説明を見つけるために、複数のバージョンを試すことが重要です。
OpenAPI仕様書
OpenAPI仕様書は、APIの詳細情報をモデルに提供する絶好の場所です。
各フィールドに対して分かりやすい名前を使用するだけでなく、仕様書にはすべての属性に対する「description」フィールドも含めることができます。
これらは、関数の機能、クエリフィールドが何を期待するかなどの情報を自然言語で提供し、モデルがAPIをどのように使用すべきかを理解するのを助けます。
また、特定の値に制約があるフィールドの場合、「enum」を用いて説明的なカテゴリ名を提供することも可能です。
description_for_model
description_for_model属性は、モデルにプラグインの一般的な使用方法について提供するためのフィールドです。
ChatGPTの背後にある言語モデルが解釈しやすいように、プラグインが何をするのか、どのように使うのかを簡潔に記載することが重要です。
OpenAI社は「Plugin for…」で始めて、APIが提供するすべての機能を列挙することを推奨しているので、その通りに書くのが良いです。
ベストプラクティス
OpenAPI仕様書のdescription_for_modelやdescriptionを記述する際、またはAPIレスポンスを設計する際のベストプラクティスは以下の通りです
①ChatGPTの制御の禁止
ChatGPTの気分、性格、具体的なレスポンスを制御しようとする説明は避けてください。ChatGPTはプラグインに対して適切なレスポンスを生成するように設計されています。
When the user asks to see their todo list, always respond with “I was able to find your todo list! You have [x] todos: [list the todos here]. I can add more todos if you’d like!
[no instructions needed for this]
②必要のないときに利用を促すことは禁止
ユーザーがあなたのプラグインの特定のカテゴリーのサービスを求めていないときに、ChatGPTにプラグインを使うように促すべきではありません。
Whenever the user mentions any type of task or plan, ask if they would like to use the TODOs plugin to add something to their todo list.
The TODO list can add, remove and view the user’s TODOs.
③特定のトリガーの禁止
ChatGPTがプラグインを使用するための特定のトリガーを記述してはいけません。ChatGPTは適切な時に自動的にあなたのプラグインを使うように設計されています。
When the user mentions a task, respond with “Would you like me to add this to your TODO list? Say ‘yes’ to continue.”
[no instructions needed for this]
④必要でない限りは生データを返す
プラグインAPIのレスポンスは、必要でない限り、自然言語のレスポンスではなく、生データを返すべきです。ChatGPTは、返されたデータを使って独自の自然言語応答を提供します。
I was able to find your todo list! You have 2 todos: get groceries and walk the dog. I can add more todos if you’d like!
{ “todos”: [ “get groceries”, “walk the dog” ] }
プラグインストアのレビューについて
プラグインストアでプラグインを利用できるようにするには、OpenAIによるレビューが必要です。
ここからは、プラグインストアにおいての審査プロセスの基本的な考え方を解説します。
レビュープロセスの目的
レビュープロセスの目的は、ChatGPTのプラグインが安全で、有用な機能を提供し、高品質のユーザーエクスペリエンスを提供することを確認することです。
評価の基準と流れ
ユーザーに新しい魔法のような体験を提供するプラグインが最も価値があると考えています。
これには、ユーザー固有の情報源の検索、他のプラグインとの相乗効果、モデルに計算能力を与えるプラグイン、新しいChatGPTの使い方を紹介するプラグインなどが含まれます。
また、以下の基準のいずれかが欠けている場合、プラグインはレビューで却下されます。
- コンテンツポリシーとブランドガイドラインに準拠していること。
- 提出したプラグインが記載通りに機能すること。
- 有益なエラーメッセージを提供すること。
- 操作名が説明的であること。
- シンプルで簡潔なマニフェストファイルを提供すること。
- 正しい文法を使用し、プラグインの説明を句読点で終わらせること。
- ユーザーの混乱を避けるため、プラグインの説明で地理的または機能的な制限を明確に述べること。
- プラグイン名や説明文に「plugin」、「ChatGPT」、「OpenAI」などの単語を使用しないこと。
プラグインをレビューに提出すると、通常は7日以内に返信があります。新しいプラグインは順次レビューされ、提出にはプラグイン提出ボットを使用します。ボットを表示するにはログインが必要です。
プラグインの提出状況は、ログイン状態で「ヘルプ」を選択することで確認できます。プラグインのステータスが審査中に変更された場合、通知があります。
ChatGPTプラグインを開発する上での注意点
①プラグインの名前を付ける際には、ブランドガイドラインに沿った名前をつける
OpenAI社が公開しているガイドラインに従わないプラグインは、プラグインストアで承認されません。
例えば、〇〇GPTやGPT〇〇という名前は禁止されているため、プラグインストアで承認されない可能性が高いです。
ブランドガイドラインは以下の記事でまとめているので、プラグインの名前を考えるときはぜひ参考にしてみてください
クイックスタート
OpenAI社は開発者が5分以内にプラグインを動かせるように、「プラグインクイックスタート」を公開しています。
プラグインを試したことがない方は、まずは「プラグインクイックスタート」から始めてみることで、プラグインを動かすための基本的な手順を学ぶことができます。
プラグインのサンプルコード
OpenAI社の公式で紹介されているプラグイン例です。
例①シンプルなスポーツ統計プラグインの構築方法
このプラグインは、シンプルなスポーツ統計APIの一例です。実際にプラグインを作る際には、ドメインポリシーや利用ポリシーに留意してください。
まず、以下のフィールドを持つai-plugin.jsonファイルを定義します
1{
2 "schema_version": "v1",
3 "name_for_human": "Sport Stats",
4 "name_for_model": "sportStats",
5 "description_for_human": "Get current and historical stats for sport players and games.",
6 "description_for_model": "Get current and historical stats for sport players and games. Always display results using markdown tables.",
7 "auth": {
8 "type": "none"
9 },
10 "api": {
11 "type": "openapi",
12 "url": "PLUGIN_HOSTNAME/openapi.yaml",
13 "is_user_authenticated": false
14 },
15 "logo_url": "PLUGIN_HOSTNAME/logo.png",
16 "contact_email": "support@example.com",
17 "legal_info_url": "https://example.com/legal"
18}
PLUGIN_HOSTNAMEは、プラグインサーバーの実際のホスト名であることに注意してください。
次に、シンプルなスポーツサービスプラグインのモックAPI(main.py)を定義します。
1import json
2import requests
3import urllib.parse
4
5import quart
6import quart_cors
7from quart import request
8
9# Note: Setting CORS to allow chat.openapi.com is only required when running a localhost plugin
10app = quart_cors.cors(quart.Quart(__name__), allow_origin="https://chat.openai.com")
11HOST_URL = "https://example.com"
12
13@app.get("/players")
14async def get_players():
15 query = request.args.get("query")
16 res = requests.get(
17 f"{HOST_URL}/api/v1/players?search={query}&page=0&per_page=100")
18 body = res.json()
19 return quart.Response(response=json.dumps(body), status=200)
20
21
22@app.get("/teams")
23async def get_teams():
24 res = requests.get(
25 "{HOST_URL}/api/v1/teams?page=0&per_page=100")
26 body = res.json()
27 return quart.Response(response=json.dumps(body), status=200)
28
29
30@app.get("/games")
31async def get_games():
32 query_params = [("page", "0")]
33 limit = request.args.get("limit")
34 query_params.append(("per_page", limit or "100"))
35 start_date = request.args.get("start_date")
36 if start_date:
37 query_params.append(("start_date", start_date))
38 end_date = request.args.get("end_date")
39
40 if end_date:
41 query_params.append(("end_date", end_date))
42 seasons = request.args.getlist("seasons")
43
44 for season in seasons:
45 query_params.append(("seasons[]", str(season)))
46 team_ids = request.args.getlist("team_ids")
47
48 for team_id in team_ids:
49 query_params.append(("team_ids[]", str(team_id)))
50
51 res = requests.get(
52 f"{HOST_URL}/api/v1/games?{urllib.parse.urlencode(query_params)}")
53 body = res.json()
54 return quart.Response(response=json.dumps(body), status=200)
55
56
57@app.get("/stats")
58async def get_stats():
59 query_params = [("page", "0")]
60 limit = request.args.get("limit")
61 query_params.append(("per_page", limit or "100"))
62 start_date = request.args.get("start_date")
63 if start_date:
64 query_params.append(("start_date", start_date))
65 end_date = request.args.get("end_date")
66
67 if end_date:
68 query_params.append(("end_date", end_date))
69 player_ids = request.args.getlist("player_ids")
70
71 for player_id in player_ids:
72 query_params.append(("player_ids[]", str(player_id)))
73 game_ids = request.args.getlist("game_ids")
74
75 for game_id in game_ids:
76 query_params.append(("game_ids[]", str(game_id)))
77 res = requests.get(
78 f"{HOST_URL}/api/v1/stats?{urllib.parse.urlencode(query_params)}")
79 body = res.json()
80 return quart.Response(response=json.dumps(body), status=200)
81
82
83@app.get("/season_averages")
84async def get_season_averages():
85 query_params = []
86 season = request.args.get("season")
87 if season:
88 query_params.append(("season", str(season)))
89 player_ids = request.args.getlist("player_ids")
90
91 for player_id in player_ids:
92 query_params.append(("player_ids[]", str(player_id)))
93 res = requests.get(
94 f"{HOST_URL}/api/v1/season_averages?{urllib.parse.urlencode(query_params)}")
95 body = res.json()
96 return quart.Response(response=json.dumps(body), status=200)
97
98
99@app.get("/logo.png")
100async def plugin_logo():
101 filename = 'logo.png'
102 return await quart.send_file(filename, mimetype='image/png')
103
104
105@app.get("/.well-known/ai-plugin.json")
106async def plugin_manifest():
107 host = request.headers['Host']
108 with open("ai-plugin.json") as f:
109 text = f.read()
110 # This is a trick we do to populate the PLUGIN_HOSTNAME constant in the manifest
111 text = text.replace("PLUGIN_HOSTNAME", f"https://{host}")
112 return quart.Response(text, mimetype="text/json")
113
114
115@app.get("/openapi.yaml")
116async def openapi_spec():
117 host = request.headers['Host']
118 with open("openapi.yaml") as f:
119 text = f.read()
120 # This is a trick we do to populate the PLUGIN_HOSTNAME constant in the OpenAPI spec
121 text = text.replace("PLUGIN_HOSTNAME", f"https://{host}")
122 return quart.Response(text, mimetype="text/yaml")
123
124
125def main():
126 app.run(debug=True, host="0.0.0.0", port=5001)
127
128
129if __name__ == "__main__":
130 main()
最後に、OpenAPI仕様の定義を行います
1openapi: 3.0.1
2info:
3 title: Sport Stats
4 description: Get current and historical stats for sport players and games.
5 version: "v1"
6servers:
7 - url: PLUGIN_HOSTNAME
8paths:
9 /players:
10 get:
11 operationId: getPlayers
12 summary: Retrieves all players from all seasons whose names match the query string.
13 parameters:
14 - in: query
15 name: query
16 schema:
17 type: string
18 description: Used to filter players based on their name. For example, ?query=davis will return players that have 'davis' in their first or last name.
19 responses:
20 "200":
21 description: OK
22 /teams:
23 get:
24 operationId: getTeams
25 summary: Retrieves all teams for the current season.
26 responses:
27 "200":
28 description: OK
29 /games:
30 get:
31 operationId: getGames
32 summary: Retrieves all games that match the filters specified by the args. Display results using markdown tables.
33 parameters:
34 - in: query
35 name: limit
36 schema:
37 type: string
38 description: The max number of results to return.
39 - in: query
40 name: seasons
41 schema:
42 type: array
43 items:
44 type: string
45 description: Filter by seasons. Seasons are represented by the year they began. For example, 2018 represents season 2018-2019.
46 - in: query
47 name: team_ids
48 schema:
49 type: array
50 items:
51 type: string
52 description: Filter by team ids. Team ids can be determined using the getTeams function.
53 - in: query
54 name: start_date
55 schema:
56 type: string
57 description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or after this date.
58 - in: query
59 name: end_date
60 schema:
61 type: string
62 description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or before this date.
63 responses:
64 "200":
65 description: OK
66 /stats:
67 get:
68 operationId: getStats
69 summary: Retrieves stats that match the filters specified by the args. Display results using markdown tables.
70 parameters:
71 - in: query
72 name: limit
73 schema:
74 type: string
75 description: The max number of results to return.
76 - in: query
77 name: player_ids
78 schema:
79 type: array
80 items:
81 type: string
82 description: Filter by player ids. Player ids can be determined using the getPlayers function.
83 - in: query
84 name: game_ids
85 schema:
86 type: array
87 items:
88 type: string
89 description: Filter by game ids. Game ids can be determined using the getGames function.
90 - in: query
91 name: start_date
92 schema:
93 type: string
94 description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or after this date.
95 - in: query
96 name: end_date
97 schema:
98 type: string
99 description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or before this date.
100 responses:
101 "200":
102 description: OK
103 /season_averages:
104 get:
105 operationId: getSeasonAverages
106 summary: Retrieves regular season averages for the given players. Display results using markdown tables.
107 parameters:
108 - in: query
109 name: season
110 schema:
111 type: string
112 description: Defaults to the current season. A season is represented by the year it began. For example, 2018 represents season 2018-2019.
113 - in: query
114 name: player_ids
115 schema:
116 type: array
117 items:
118 type: string
119 description: Filter by player ids. Player ids can be determined using the getPlayers function.
120 responses:
121 "200":
122 description: OK
FAQ
プラグインデータはどう使われるの?
プラグインはChatGPTと外部アプリをつなげる役割を果たします。ユーザーがプラグインを使うと、その会話の一部やユーザーの住んでいる国や地域の情報がプラグインに送られることがあります。
APIへの要求がうまくいかなかったらどうなるの?
APIへの要求が失敗した場合、モデルはそのプラグインから返答が得られないとユーザーに伝える前に、最大10回まで再試行を試みます。
自分のプラグインを試してもらうために人を招待できる?
はい、確認がまだ済んでいないプラグインでも、プラグインの利用資格を持つ他の開発者15人までにインストールしてもらうことができます。
自分のプラグインの利用に対して料金を取ることはできる?
はい、可能です。プラグインを運用するにはコストがかかるので、無料で使えるAPIの回数を限定的に設定することをお勧めします。
プラグイン開発事例
食べログプラグイン開発
この記事は食べログがChatGPTプラグインを開発した過程を詳しく説明しています。
ただ開発の技術的な部分だけでなく、サービス設計や各部門との連携、法務との交渉など、プラグイン開発にまつわる多角的な課題についても触れています。
ChatGPTのプラグイン開発を考えている人にとって、実際の経験談として非常に参考になる内容となっています。
AWSでのプラグイン開発
この記事は、AWS LambdaでChatGPTプラグインを開発し、それをAWS環境にデプロイする手順を詳細に説明しています。
特に、AWS環境向けのプラグインマニフェスト/API仕様の作成、AWS CDKスクリプトの記述、静的リソースを格納するS3バケットの設定、およびCloudFrontディストリビューション(CDN)の設定について解説しています。
AWSでのプラグイン開発を考えている人はぜひ参考にしてみてください
BOXIL SaaSプラグイン開発
この記事はBOXIL SaaSがChatGPTプラグインを開発した過程を詳しく説明しています。
開発の様子はもちろんのこと、プラグインの申請から承認までどれくらいの日数がかかったなども詳細に書かれているので、プラグインを実際にリリースしようと考えている人には参考になること間違いありません!
まとめ
この記事では、ChatGPTプラグインの開発に必要な全てのステップを詳しく解説しました。
ChatGPTのプラグインはβ版がリリースされたばかりなので、まだプラグインストアにはプラグインが100種類も存在していません。
なので、ぜひこの記事を参考に世界的に人気のプラグインを作れるように試していただければと思います。
また情報が更新され次第、追記していきます。
それでは!
おすすめのプラグインについては以下の記事で紹介しているので、便利なプラグインを使うことで生産性を上げたい人はぜひこちらも参考にしてみてください。