-
[Chat gpt] Plugin 개발하기카테고리 없음 2023. 8. 5. 17:42
Chat gpt Plugin 이란..
나의 서비스에 ChatGPT를 plugin하는 것이 아니라 ChatGPT에 나의 서비스를 결합하는 기능
Plugin Flow
1) manifest file 생성
- manifest 파일은 내 도메인의 특정 경로에 존재해야함 (domain.com/.well-known/ai-plugin.json)
- plugin meta에 대한 설명이 있어야함 (name, logo, 등)
- 인증이 필요한 경우 Oauth URL 등 인증과 관련된 정보를 제공해야함
- OpenAPI spec 지정
* 이 때 endpoint 수를 1-2개 정도로 제한하여 토큰 수를 줄이는 것을 권장하는데, plugin 설명과 API 요청, API
response가 모두 ChatGPT와의 대화 기록에 들어가기 때문이다. 이 말은 즉 모델의 토큰 리밋에 해당된다는 것.
2) ChatGPT UI에서 plugin을 등록
3) 유저가 plugin을 수동으로 activate해주어야함
- OpenAI 측에서 ChatGPT에게 메시지로 plugin에 대한 compact한 설명을 전달, 유저는 이 메시지를 보지 못한다. 이 때 plugin 설명, endpoint, example을 포함하여 GPT가 스스로 plugin을 언제 호출해야 적당할지에 대해 판단할 수 있게 한다.
- 유저와의 대화 중에 plugin과 연관된 내용이 있다면 ChatGPT가 plugin을 호출할 것인지 판단하게 된다. (단, 만약 POST API라면 plugin 개발자가 직접 user confirmation flow를 짜야함)
- API 콜에 대한 응답 결과는 rich preview로 보여진다. (이 때 OpenGraph protocol 사용)
ChatGPT plugin 만들기 = 위 Plugin Flow 에서 "manifest file 생성"
1) 내 서비스의 API 만들기
2) API를 document화하여 OpenAI yaml파일이나 JSON파일로 담기
3) JSON Manifest 파일을 만들어 plugin 메타에 대한 정보를 담기
총 3단계를 통해 plugin을 완성할 수 있다.
chat gpt 에서 제공하는 예제를 통해 알아보자
예제 (https://github.com/openai/plugins-quickstart)폴더 구조
ㄴ .well-known ( 폴더 )
ㄴ main.py
ㄴ openapi.yaml
ㄴ requirements.txt
소스 작성
1. main.py 내 간단한 서비스 작성
import json
import quartimport quart_corsfrom quart import request
# Keep track of todo's. Does not persist if Python session is restarted._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"]# fail silently, it's a simple pluginif 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("./.well-known/ai-plugin.json") as f:text = f.read()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()return quart.Response(text, mimetype="text/yaml")
def main():app.run(debug=True, host="0.0.0.0", port=5003)
if __name__ == "__main__":main()python 을 잘 모르나.. 코드만 봐도 자바에 비해선 압도적으로 간단하다.. ㅎㅎ
def main():app.run(debug=True, host="0.0.0.0", port=5003)로컬 서버 run 을 위 한줄로 하다니 .. 비교 차원에서 자바 서버 구축 예시를 첨부한다.
너무 길어서 링크로... (https://heodolf.tistory.com/133)
언뜻 코드를 보니.. open api 쪽에서 아래 두 파일을 참조하는 듯 싶다.
@app.get("/.well-known/ai-plugin.json")
@app.get("/openapi.yaml")
그럼 이제 위의 해당하는 두 파일을 만들어보자.
2. ai-plugin.json 파일 생성
해당 파일을 생성하여 API 도메인에 호스팅해야한다. 이때 반드시 도메인 아래 /.well-known 폴더에 있어야한다.
{"schema_version": "v1","name_for_human": "TODO List (no auth)", // plugin 이름"name_for_model": "todo", // 모델이 plugin 을 사용할 때 쓸 이름"description_for_human": "Manage your 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:5003/openapi.yaml" // 내가 서비스하고있는 api 도메인.},"logo_url": "http://localhost:5003/logo.png","contact_email": "legal@example.com",}3. openapi.yml 파일 생성 = OpenAPI definition
OpenAPI specification에 정의된 것 외에는 ChatGPT가 API에 대해 아는 바가 전혀 없기 때문에 이를 활용하여 ChatGPT가 접근해야/해도 되는 endpoint만 지정해서 알려주는 것이 좋다. 예를 들어 소셜미디어 API라고 한다면 유저들의 포스트에 코멘트를 남기는 등의 API는 자제하고, content 자체에 대한 access를 할 수 있는 API만을 오픈한다는지 등이다.
아래는 예제 서비스의 api definition 이다.
openapi: 3.0.1 // version 정보 : yaml 파일의 가장 위쪽에 기술함info:title: TODO Plugin // api 제목 ( 필수 작성 )description: A plugin that allows the user to create and manage a TODO list using ChatGPT. If you do not know the user's username, ask them first before making queries to the plugin. Otherwise, use the username "global".version: 'v1' // api 버전 정보 ( 필수 작성 )servers: // target 되는 host server 의 주소를 기록해두는 필드. optional 한 필드이며 없을때 기본 url 은 '/'- url: http://localhost:5003 // 위 main.py 를 보면 알겠지만 localhost:5003 으로 서버를 띄우므로 이렇게 작성함.paths: // 실제 api 는 다 이 path 에서 작성함/todos/{username}:get:operationId: getTodossummary: Get the list of todosparameters:- in: pathname: usernameschema:type: stringrequired: truedescription: The name of the user.responses: // get 으로 위 url 로 들어오면... response 는 아래와 같이 보내네"200": // 정상적으로 들어왔을땐description: OKcontent:application/json:schema:$ref: '#/components/schemas/getTodosResponse' // 요 components 들에 대해선 아래에서 기술post:operationId: addTodosummary: Add a todo to the listparameters:- in: pathname: usernameschema:type: stringrequired: truedescription: The name of the user.requestBody:required: truecontent:application/json:schema:$ref: '#/components/schemas/addTodoRequest'responses:"200":description: OKdelete:operationId: deleteTodosummary: Delete a todo from the listparameters:- in: pathname: usernameschema:type: stringrequired: truedescription: The name of the user.requestBody:required: truecontent:application/json:schema:$ref: '#/components/schemas/deleteTodoRequest'responses:"200":description: OK
components: // 재사용가능한 object 들을 모아둔 곳이 바로 이 component 임schemas:getTodosResponse:type: objectproperties:todos:type: arrayitems:type: stringdescription: The list of todos.addTodoRequest:type: objectrequired:- todoproperties:todo:type: stringdescription: The todo to add to the list.required: truedeleteTodoRequest:type: objectrequired:- todo_idxproperties:todo_idx:type: integerdescription: The index of the todo to delete.required: true4. 끝 ! 의잉..? 생각보다 별거없다.
이제 chatgpt UI 에서 플러그인만 등록해주면된다.
( 단 2023.08 월 기준 플러그인은 chatgpt 4에서만 지원해주므로.. 월 20달러 구독을 하면 사용까진 자유롭게 할 수 있음.
다만 plugin 등록은 waiting list 에 등록하고 기다리면 openapi 쪽에서 검토하고 plugin 등록 권한을 부여해주는 듯 하다.)
waiting list 에 등록은 해뒀고.. 승인나면 올려봐야지 ㅎㅎ
다음에는 plug in 등록 포스트로 돌아오겠다.
댓글