Chapter 4. ํ”Œ๋Ÿฌ๊ทธ์ธ ์ œ์ž‘ํ•ด๋ณด๊ธฐ (feat. ChatGPT)


๋ˆˆ์น˜๊ฐ€ ๋น ๋ฅธ ๋…์ž๋“ค์€ "์–ด์ฐจํ”ผ ์ด๊ฑธ ์ ๋Š” ๊ฒƒ์€ ๋‹น์‹ ์ด ์•„๋‹ ๊ฒƒ์ด๋‹ค"์—์„œ ์ด ๊ธ€์˜ ์ œ๋ชฉ์˜ ์˜๋ฏธ๋ฅผ ์•Œ์•„๋ดค์„ ์ˆ˜๋„ ์žˆ๋‹ค


๊ทธ๋ ‡๋‹ค. '์šฐ๋ฆฌ'๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๋‹ค.

์™œ๋ƒ? ํ”Œ๋Ÿฌ๊ทธ์ธ ์ฝ”๋“œ๋Š” ์šฐ๋ฆฌ ๋Œ€๋ถ€๋ถ„๋ณด๋‹ค ChatGPT๊ฐ€ ๋” ์ž˜ ์“ฐ๋‹ˆ.


์•ž์œผ๋กœ ์šฐ๋ฆฌ๋Š”, '๋”ธ๊น' ํ•œ ๋ฒˆ์œผ๋กœ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ œ์ž‘ํ•  ๊ฑฐ๋‹ค. ์„ค๋ ˆ์ง€ ์•Š๋Š”๊ฐ€?

์ด ๊ธ€์—์„œ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ž‘์„ฑํ•ด ์ค„ํ…Œ๋‹ˆ, ๋ณธ์ธ์˜ ๊ธฐํ˜ธ์— ๋งž๊ฒŒ ๊ด„ํ˜ธ์•ˆ์˜ ๋‚ด์šฉ์„ ์ˆ˜์ •๋งŒ ํ•˜๋ฉด ๋œ๋‹ค!

GPT 3.5 ๋ณด๋‹จ 4๋ฅผ, ํ•œ๊ตญ์–ด๋ณด๋‹จ ์˜์–ด๋ฅผ ์“ฐ๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•œ๋‹ค

*ํ”„๋กฌํ”„ํŠธ๋Š” ํ•˜๋Š˜์ƒ‰ ๋ฐ”ํƒ•์œผ๋กœ ํ‘œ์‹œํ•จ


1. ํ”Œ๋Ÿฌ๊ทธ์ธ ์•„์ด๋””์–ด ์ •๋ฆฌํ•˜๊ธฐ

๋„Œ ์ง€๊ธˆ๋ถ€ํ„ฐ (๋ณธ์ธ์ด ์›ํ•˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ธฐ๋Šฅ) ์„ ํ•˜๋Š” ChatGPT ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋งŒ๋“œ๋Š” ๊ฐœ๋ฐœ์ž์•ผ

์•„๋ž˜ ๋นˆ์นธ($ ํ‘œ์‹œ)์„ ์˜์–ด๋กœ ์ฑ„์›Œ๋ด


Scope and idea for the app:

$GENERAL_PROJECT_SCOPE

The plugin has one main functionality which allows the user to say something like:

$EXAMPLE_PROMPTS

The endpoint will receive:

$INFO_NEEDED_FOR_FUNCTIONALITY (eg, date, stock name, url)

ChatGPT will take in the userโ€™s prompt and extract these fields before sending it to the API endpoint.

The user is not able to:

$FUNCTIONALITY_LIMIT


์œ„ ํ”„๋กฌํ”„ํŠธ๋Š” ChatGPT์—๊ฒŒ ๋‹น์‹ ์ด ๋งŒ๋“ค๊ณ ์ž ํ•˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์„ค๋ช…ํ•ด์ฃผ๊ณ 

๊ทธ ๋‚ด์šฉ์„ ChatGPT๊ฐ€ ์•Œ์•„์„œ ๋ฐœ์ „์‹œ์ผœ (+์˜์–ด๋กœ) ์ •๋ฆฌํ•˜๋„๋ก ์ž๋™ํ™” ํ•ด์ฃผ๋Š” ํ”„๋กฌํ”„ํŠธ๋‹ค

์ด ํ”„๋กฌํ”„ํŠธ์— ๋Œ€ํ•œ ๋‹ต์žฅ์„ ๋ณต์‚ฌํ•˜๊ณ  2๋ฒˆ์œผ๋กœ ๋„˜์–ด๊ฐ€์ž


2. ํ”Œ๋Ÿฌ๊ทธ์ธ ์ฝ”๋“œ ์•„์›ƒ์†Œ์‹ฑํ•˜๊ธฐ


(1๋ฒˆ ํ”„๋กฌํ”„ํŠธ๋กœ ์–ป์€ ๋‹ต์žฅ)

Information on any API's that will be used to create this app and the docs for the functionality required:

(์‚ฌ์šฉํ•˜๋ ค๋Š” API์— ๋Œ€ํ•œ ์ž๋ฃŒ)

Below is a main.py file showing an example of a basic plugin app:

import json


import quart

import quart_cors

from quart import request


# Note: Setting CORS to allow chat.openapi.com is only required when running a localhost plugin

app = quart_cors.cors(quart.Quart(__name__), allow_origin="https://chat.openai.com")


_TODOS = {}



@app.post("/todos/<string:username>")

async def add_todo(username):

request = await quart.request.get_json(force=True)

if username not in _TODOS:

_TODOS[username] = []

_TODOS[username].append(request["todo"])

return quart.Response(response='OK', status=200)



@app.get("/todos/<string:username>")

async def get_todos(username):

return quart.Response(response=json.dumps(_TODOS.get(username, [])), status=200)



@app.delete("/todos/<string:username>")

async def delete_todo(username):

request = await quart.request.get_json(force=True)

todo_idx = request["todo_idx"]

if 0 <= todo_idx < len(_TODOS[username]):

_TODOS[username].pop(todo_idx)

return quart.Response(response='OK', status=200)



@app.get("/logo.png")

async def plugin_logo():

filename = 'logo.png'

return await quart.send_file(filename, mimetype='image/png')



@app.get("/.well-known/ai-plugin.json")

async def plugin_manifest():

host = request.headers['Host']

with open("ai-plugin.json") as f:

text = f.read()

# This is a trick we do to populate the PLUGIN_HOSTNAME constant in the manifest

text = text.replace("PLUGIN_HOSTNAME", f"https://{host}")

return quart.Response(text, mimetype="text/json")



@app.get("/openapi.yaml")

async def openapi_spec():

host = request.headers['Host']

with open("openapi.yaml") as f:

text = f.read()

# This is a trick we do to populate the PLUGIN_HOSTNAME constant in the OpenAPI spec

text = text.replace("PLUGIN_HOSTNAME", f"https://{host}")

return quart.Response(text, mimetype="text/yaml")



def main():

app.run(debug=True, host="0.0.0.0", port=5002)



if __name__ == "__main__":

main()


Important notes:

Be sure to set a conservative limit on the size of the response the app tries to return to ensure the character limit of 100k characters is not exceeded.

Make sure the API endpoints name eg "/news" matches up with what is written in the OpenAPI definition.

Include a custom logging handler on all visits to URLs and important app events as in the above examples

Do not leave placeholders in, replace all of them with the correct info so that I can copy and paste this and it is ready to launch.

Make sure the routes for '/.well-known/ai-plugin.jsonโ€™ and '/.well-known/openapi.yaml' are reused exactly as shown above.

Now, I need you to create the main.py file for my app.

API์— ๋Œ€ํ•œ ์ž๋ฃŒ๋Š” ์ธํ„ฐ๋„ท์—์„œ ๊ฒ€์ƒ‰ํ•œ ๊ณต์‹ ๋ฌธ์„œ ๊ทธ๋ƒฅ ๋ณต๋ถ™ํ•˜๋ฉด ๋œ๋‹ค

ํ•„์ž๋Š” ๋‹ค์Œ์„ ์ด์šฉํ–ˆ๋‹ค(https://github.com/jdepoix/youtube-transcript-api)

์—ฌ๊ธฐ๊นŒ์ง€ ํ–ˆ๋‹ค๋ฉด ์ถ•ํ•˜ํ•œ๋‹ค.

๋ฐฉ๊ธˆ ํ”Œ๋Ÿฌ๊ทธ์ธ์˜ ํ•ต์‹ฌ ์ฝ”๋“œ๋ฅผ ๋‹ค ์ž‘์„ฑํ–ˆ๋‹ค.

์ด ์ฏค์—์„œ ChatGPT ๋Œ€ํ™”์ฐฝ์„ ์ƒˆ๋กœ ํŒŒ๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•œ๋‹ค(API ์ž๋ฃŒ๊ฐ€ ๋„ˆ๋ฌด ๊ธธ ๊ฒฝ์šฐ ๋Œ€ํ™”๋‚ด์šฉ์„ ๊นŒ๋จน์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž„)


3. ai-plugin.json ์ž‘์„ฑํ•˜๊ธฐ


Now I need you to write me a manifest file for my plugin. Here are the OpenAI docs on how to create a manifest file:

Plugin manifest

Every plugin requires a ai-plugin.json file, which needs to be hosted on the APIโ€™s domain. For example, a company called example.com would make the plugin JSON file accessible via an https://example.com domain since that is where their API is hosted. When you install the plugin via the ChatGPT UI, on the backend we look for a file located at /.well-known/ai-plugin.json. The /.well-known folder is required and must exist on your domain in order for ChatGPT to connect with your plugin. If there is no file found, the plugin cannot be installed. For local development, you can use HTTP but if you are pointing to a remote server, HTTPS is required.

The minimal definition of the required ai-plugin.json file will look like the following:

{

"schema_version": "v1",

"name_for_human": "TODO Plugin",

"name_for_model": "todo",

"description_for_human": "Plugin for managing a TODO list. You can add, remove and view your TODOs.",

"description_for_model": "Plugin for managing a TODO list. You can add, remove and view your TODOs.",

"auth": {

"type": "none"

},

"api": {

"type": "openapi",

"url": "<http://localhost:3333/openapi.yaml>",

"is_user_authenticated": false

},

"logo_url": "<http://localhost:3333/logo.png>",

"contact_email": "support@example.com",

"legal_info_url": "<http://www.example.com/legal>"

}


If you want to see all of the possible options for the plugin file, you can refer to the definition below.

FIELD

TYPE

DESCRIPTION / OPTIONS

REQUIRED

schema_version

String

Manifest schema version

โœ…

name_for_model

String

Name the model will used to target the plugin

โœ…

name_for_human

String

Human-readable name, such as the full company name

โœ…

description_for_model

String

Description better tailored to the model, such as token context length considerations or keyword usage for improved plugin prompting.

โœ…

description_for_human

String

Human-readable description of the plugin

โœ…

auth

ManifestAuth

Authentication schema

โœ…

api

Object

API specification

โœ…

logo_url

String

URL used to fetch the plugin's logo

โœ…

contact_email

String

Email contact for safety/moderation reachout, support, and deactivation

โœ…

legal_info_url

String

Redirect URL for users to view plugin information

โœ…

HttpAuthorizationType

HttpAuthorizationType

"bearer" or "basic"

โœ…

ManifestAuthType

ManifestAuthType

"none", "user_http", "service_http", or "oauth"



interface BaseManifestAuth

BaseManifestAuth

type: ManifestAuthType; instructions: string;



ManifestNoAuth

ManifestNoAuth

No authentication required: BaseManifestAuth & { type: 'none', }



ManifestAuth

ManifestAuth

ManifestNoAuth, ManifestServiceHttpAuth, ManifestUserHttpAuth, ManifestOAuthAuth




There are also some limits to the length of certain field in the manifest file that are subject to change over time:

50 character max for**name_for_human**

50 character max for name_for_model

120 character max for description_for_human

8000 character max just for description_for_model (will decrease over time)

Separately, we also have a 100k character limit (will decrease over time) on the API response body length which is also subject to change.

Here is my application:

(2๋ฒˆ์—์„œ ๋ฐ›์€ ์ฝ”๋“œ ๋ณต๋ถ™)

Write a manifest file for my app.


description_for_model ๋ถ€๋ถ„์€ ๋˜๋„๋ก์ด๋ฉด ์ง์ ‘ ์ž‘์„ฑํ•˜์ž
์˜์–ด๋ฅผ ๋ชจ๋ฅธ๋‹ค๋ฉด DeepL์„ ์“ฐ๋“  GPT๋ฅผ ์จ์„œ ์‹œํ‚ค๋“  ํ•˜์ž
description_for_model์„ ์“ธ ๋•Œ OpenAI์˜ ์˜คํ”ผ์…œ ํŒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค:
์ถœ์ฒ˜ : https://platform.openai.com/docs/plugins/getting-started/writing-descriptions
  • ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์“ธ ๋•Œ์˜ GPT์˜ ๋งํˆฌ, ์‘๋‹ต ํ˜•์‹์„ ๊ณ ์ •์ ์œผ๋กœ ์ •ํ•˜๋ ค๊ณ  ํ•˜์ง€ ๋ง ๊ฒƒ
  • ์‚ฌ์šฉ์ž๊ฐ€ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์“ฐ๋„๋ก ์œ ๋„ํ•˜๋ผ ์ง€์‹œํ•˜์ง€ ๋ง ๊ฒƒ
  • ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋ฐœ๋™์‹œํ‚ค๊ธฐ ์œ„ ์ผ์ข…์˜ 'trigger ํ”„๋กฌํ”„ํŠธ'๋ฅผ ์ •ํ•ด๋†“์ง€ ๋ง ๊ฒƒ
4. openapi.yaml ์ž‘์„ฑํ•˜๊ธฐ

Now I need you to write me an openAPI definition for my plugin. Here are the OpenAI docs on how to create one correctly:
OpenAPI definition
The next step is to build the OpenAPI specification to document the API. The model in ChatGPT does not know anything about your API other than what is defined in the OpenAPI specification and manifest file. This means that if you have an extensive API, you need not expose all functionality to the model and can choose specific endpoints. For example, if you have a social media API, you might want to have the model access content from the site through a GET request but prevent the model from being able to comment on users posts in order to reduce the chance of spam.
The OpenAPI specification is the wrapper that sits on top of your API. A basic OpenAPI specification will look like the following:
`openapi: 3.0.1 info: title: TODO Plugin description: A plugin that allows the user to create and manage a TODO list using ChatGPT. version: 'v1' servers:
url: http://localhost:3333 paths: /todos: get: operationId: getTodos summary: Get the list of todos responses: "200": description: OK content: application/json: schema: $ref: '#/components/schemas/getTodosResponse' components: schemas: getTodosResponse: type: object properties: todos: type: array items: type: string description: The list of todos.`
We start by defining the specification version, the title, description, and version number. When a query is run in ChatGPT, it will look at the description that is defined in the info section to determine if the plugin is relevant for the user query. You can read more about prompting in the writing descriptions section.
Keep in mind the following limits in your OpenAPI specification, which are subject to change:
200 characters max for each API endpoint description/summary field in API specification
200 characters max for each API param description field in API specification
Since we are running this example locally, we want to set the server to point to your localhost URL. The rest of the OpenAPI specification follows the traditional OpenAPI format, you can learn more about OpenAPI formatting through various online resources. There are also many tools that auto generate OpenAPI specifications based on your underlying API code.
Here is an example of a working OpenAPI definition from a plugin I made previously:

openapi: 3.0.1
info:
title: TODO Plugin
description: A plugin that allows the user to create and manage a TODO list using ChatGPT.
version: 'v1'
servers:
- url: http://localhost:3333
paths:
/todos:
get:
operationId: getTodos
summary: Get the list of todos
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/getTodosResponse'
components:
schemas:
getTodosResponse:
type: object
properties:
todos:
type: array
items:
type: string
description: The list of todos.

Here is my application:

(2๋ฒˆ์—์„œ ๋ฐ›์€ ์ฝ”๋“œ ๋ณต๋ถ™)

Write me an OpenAPI definition for my app. Provide only the code.

์ด์ œ ๊ฑฐ์˜ ๋‹ค์™”๋‹ค

5. ํ”Œ๋Ÿฌ๊ทธ์ธ ํŒŒ์ผ ์ €์žฅ
์•„๋ฌด ์œ„์น˜์—๋‚˜ ํด๋”๋ฅผ ๋งŒ๋“ค์ž
์ด ํด๋”๋Š” ์šฐ๋ฆฌ๊ฐ€ ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ด€๋ จ ํŒŒ์ผ๋“ค์„ ์ €์žฅํ•  ํด๋”๋‹ค
๊ทธ ํด๋” ์•ˆ์— ./well-known ์ด๋ผ๋Š” ํด๋”๋ฅผ ํ•˜๋‚˜ ๋” ๋งŒ๋“ค์ž
./well-known์ด๋ผ๋Š” ํด๋” ์•ˆ์— ai-plugin.json, openapi.yaml, logo.png ๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ํŒŒ์ผ๋“ค์„ ๋„ฃ์ž

๊ทธ ๋‹ค์Œ ์—ฌ๊ธฐ๋กœ ๊ฐ€์„œ ์ปดํ“จํ„ฐ์— git์„ ์„ค์น˜ํ•˜์ž

๊ทธ๋ฆฌ๊ณ  github ๊ณ„์ •์„ ํ•˜๋‚˜ ๋งŒ๋“ ๋‹ค

new repository๋ฅผ ํด๋ฆญํ•ด ์›๊ฒฉ ์ €์žฅ์†Œ๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ ๋‹ค


ํ”Œ๋Ÿฌ๊ทธ์ธ ํŒŒ์ผ(./well-known '๋ง๊ณ ')์˜ ๋นˆ๊ณต๊ฐ„์— ์šฐํด๋ฆญ์„ ํ•˜๋ฉด ๋‚˜์˜ค๋Š” ๋ฉ”๋‰ด ์ค‘ git bash here ์„ ๋ˆ„๋ฅธ๋‹ค
๊ทธ๋Ÿฌ๋ฉด ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋Š” ์ฐฝ์ด ํ•˜๋‚˜ ๋œฌ๋‹ค

๋‹ค์Œ์˜ ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•œ๋‹ค
git remote add origin <์•„๊นŒ ๋งŒ๋“  repository ๋งํฌ>

6. ํ”Œ๋Ÿฌ๊ทธ์ธ ํ˜ธ์ŠคํŒ…ํ•˜๊ธฐ
ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ํ˜ธ์ŠคํŒ…ํ•˜๋Š” ๋ฐ์—๋Š” ๋‹ค์–‘ํ•œ ํ˜ธ์ŠคํŒ… ์„œ๋น„์Šค๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค
ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ๋ฌด๋ฃŒ๊ฐ€ ์ข‹์œผ๋ฏ€๋กœ, ์ด ๊ธ€์—์„œ๋Š” ๋ฌด๋ฃŒ ํ”Œ๋žœ(render, vercel)์ด ์žˆ๋Š” ์„œ๋น„์Šค๋ฅผ ์ด์šฉํ•  ๊ฒƒ์ด๋‹ค

์ด ๊ธ€์—์„œ๋Š” render๋ฅผ ์ด์šฉํ•˜๊ฒ ๋‹ค


render์—์„œ github์œผ๋กœ ๋กœ๊ทธ์ธ ํ•œ๋’ค dashboard๋กœ ๊ฐ„๋‹ค

์˜ค๋ฅธ์ชฝ ์œ„ ํŒŒ๋ž€์ƒ‰์œผ๋กœ ๋‚˜์™€์žˆ๋Š” New+ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ณ  Web service๋ฅผ ์„ ํƒํ•œ๋‹ค

Connect a repository์—์„œ ์•„๊นŒ ๋งŒ๋“ค์—ˆ๋˜ ํ”Œ๋Ÿฌ๊ทธ์ธ repository๋ฅผ ์„ ํƒํ•œ๋‹ค

์ฑ„์›Œ์•ผ ํ•  ๋ž€๋“ค์„ ์ „๋ถ€ ์ฑ„์šฐ๊ณ  free plan์„ ์„ ํƒํ•œ๋‹ค

๋งจ ์•„๋ž˜ launch web service๋ฅผ ํด๋ฆญํ•œ๋‹ค


๊ฑฐ์˜ ๋‹ค์™”๋‹ค!


7. ai-plugin.json, openapi.yaml ์™„์„ฑํ•˜๊ธฐ


render์— ํ˜ธ์ŠคํŒ…์„ ์‹œํ‚ค๊ณ  ๋‚˜์„œ, ๋‹น์‹ ์˜ ์›น์„œ๋น„์Šค๊ฐ€ ํ˜ธ์ŠคํŒ… ๋˜๊ณ  ์žˆ๋Š” ๋งํฌ์— /ai-plugin.json ์„ ๋ถ™์ธ ๋‹ค์Œ ์—”ํ„ฐ๋ฅผ ๋ˆ„๋ฅด์ž

๋ณธ์ธ์˜ ai-plugin.json ํŒŒ์ผ์˜ ๋‚ด์šฉ์ด ๋ณด์ธ๋‹ค๋ฉด ์„ฑ๊ณต์ ์œผ๋กœ ํ˜ธ์ŠคํŒ… ๋˜์—ˆ๋‹ค๋Š” ๋œป์ด๋‹ค


ai-plugin.json์—์„œ, ๋‹ค์Œ์˜ ์ค„์„ ๋‹น์‹ ์˜ ์›น์‚ฌ์ดํŠธ์™€ ํ•จ๊ป˜ ์ˆ˜์ •ํ•˜์ž


"api": {

"type": "openapi",

"url": "(์›น์‚ฌ์ดํŠธ ๋งํฌ)/.well-known/openapi.yaml",

"is_user_authenticated": false

},

"logo_url": "(์›น์‚ฌ์ดํŠธ ๋งํฌ)/.well-known/logo.png",


openapi.yaml์—์„œ, ๋‹ค์Œ์˜ ์ค„์„ ๋‹น์‹ ์˜ ์›น์‚ฌ์ดํŠธ์™€ ํ•จ๊ป˜ ์ˆ˜์ •ํ•˜์ž


version: 'v1'

servers:

- url: (์›น์‚ฌ์ดํŠธ ๋งํฌ)


legal_info_url์˜ ๊ฒฝ์šฐ,

ํ”Œ๋Ÿฌ๊ทธ์ธ์˜ ๋ฒ•์  ์ •๋ณด๋ฅผ ์ ์–ด ๋†“์€ ์›น์‚ฌ์ดํŠธ๊ฐ€ ํ•„์š”ํ•˜๋‹ค

์ด๋ฒˆ์—๋„ ๋ฌด๋ฃŒ ํ˜ธ์ŠคํŒ… ์‚ฌ์ดํŠธ๋ฅผ ์“ธ ๊ฒƒ์ด๋‹ค

๋ณธ๋ฌธ์—์„  github pages๋ฅผ ์ด์šฉํ•˜๊ฒ ๋‹ค


๋ฒ•๋ฅ ์ ์ธ ๋‚ด์šฉ์„ ์ ์–ด ๋†“๋Š” ๋ถ€๋ถ„์ด๊ธฐ ๋•Œ๋ฌธ์— ์ž˜ ๋ชจ๋ฅด๋ฉด ๊ทธ๋ƒฅ GPT์—๊ฒŒ ์ ์–ด๋‹ฌ๋ผ๊ณ  ํ•˜์ž

index.html์„ ๋งŒ๋“ค์–ด github pages์šฉ repository์— ์ €์žฅํ•œ๋‹ค


ai-plugin.json์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•œ๋‹ค

"legal_info_url": "<github pages ๋งํฌ>"


contact email ์ ๋Š” ๊ฒƒ๋„ ๋นผ๋จน์ง€ ๋ง์ž


8. ๋‚ด๊ฐ€ ๋งŒ๋“  ํ”Œ๋Ÿฌ๊ทธ์ธ ์„ค์น˜ํ•˜๊ธฐ


์ด์ œ ๋‚ด๊ฐ€ ๋งŒ๋“  ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์ž˜ ์ž‘๋™ํ•˜๋Š”์ง€ ์‹œํ—˜ํ•ด๋ณผ ์ฐจ๋ก€๋‹ค

plugin store๋ฅผ ์—ด๊ณ , ์šฐ์ธก ํ•˜๋‹จ 'Develop your own plugin' ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅธ๋‹ค

ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ํ˜ธ์ŠคํŒ… ํ–ˆ๋˜ ์›น์‚ฌ์ดํŠธ ์ฃผ์†Œ ๋งํฌ๋ฅผ ์ ๋Š”๋‹ค

ai-plugin.json ํŒŒ์ผ๊ณผ openapi.yaml ํŒŒ์ผ์— ์˜ค๋ฅ˜๊ฐ€ ๋‚ฌ๋‹ค๋ฉด, ๋ฌด์—‡์ธ์ง€ ํ™•์ธํ•˜๊ณ  ํ•ด๊ฒฐํ•œ๋‹ค

์ด์ œ install for me๋ฅผ ๋ˆŒ๋Ÿฌ ์„ค์น˜ํ•˜๋ฉด ๋์ด๋‹ค!



FAQ

Q. openai.yaml์ด ๋ถ„๋ช… ์žˆ๋Š”๋ฐ ์—†๋‹ค๊ณ  ๋– ์š”

A. openapi ์ž…๋‹ˆ๋‹ค


Q. api ๊ณต์‹๋ฌธ์„œ๊ฐ€ ๋„ˆ๋ฌด ์ปค์„œ GPT์—๊ฒŒ ์ „์†กํ•  ์ˆ˜๊ฐ€ ์—†์–ด์š”

A. apiํ‚ค๋ฅผ ๋ฐœ๊ธ‰ ๋ฐ›์•„ ์—ฌ๊ธฐ์— ์ž…๋ ฅํ›„, ์ตœ๋Œ€ ํ† ํฐ ๊ธธ์ด๋ฅผ ์„ค์ • ํ›„ ๋Œ€ํ™”ํ•ด๋ณด์„ธ์š” (์ด๊ฑด ์‚ฌ์šฉ๋ฃŒ ์žˆ์Œ)

๋˜๋Š”, https://github.com/LagPixelLOL/ChatGPTCLIBot ์ด๊ฑธ ์ด์šฉํ•ด๋ณด์„ธ์š” (๋Œ“๊ธ€์— ์›ํ•˜๋Š” ์‚ฌ๋žŒ์žˆ์œผ๋ฉด ์‚ฌ์šฉ๋ฒ• ์˜ฌ๋ฆฌ๊ฒ ์Œ)


๋Œ“๊ธ€์— ์งˆ๋ฌธ ๋ฐ›์Œ