개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
Since the release of ChatGPT, we've heard from users that they love using ChatGPT on the go. Today, we’re launching the ChatGPT app for iOS.
ChatGPT가 출시된 이후로 이동 중에 ChatGPT를 사용했으면 좋겠다는 사용자의 의견을 들었습니다. 오늘 iOS용 ChatGPT 앱을 출시합니다.
The ChatGPT app is free to use and syncs your history across devices. It also integratesWhisper, our open-source speech-recognition system, enabling voice input.ChatGPT Plus subscribersget exclusive access toGPT-4’s capabilities, early access to features and faster response times, all on iOS.
ChatGPT 앱은 무료로 사용할 수 있으며 여러 기기에서 기록을 동기화합니다. 또한 오픈 소스 음성 인식 시스템인 Whisper를 통합하여 음성 입력을 가능하게 합니다. ChatGPT Plus 가입자는 iOS에서 GPT-4의 기능, 기능에 대한 조기 액세스 및 더 빠른 응답 시간에 독점적으로 액세스할 수 있습니다.
Discover the versatility of ChatGPT:
ChatGPT의 다재다능함을 알아보세요:
Instant answers: Get precise information without sifting through ads or multiple results.
즉각적인 답변: 광고나 여러 결과를 살펴보지 않고도 정확한 정보를 얻을 수 있습니다.
Tailored advice: Seek guidance on cooking, travel plans, or crafting thoughtful messages.
맞춤형 조언: 요리, 여행 계획 또는 사려 깊은 메시지 작성에 대한 지침을 구하십시오.
Creative inspiration: Generate gift ideas, outline presentations, or write the perfect poem.
창의적인 영감: 선물 아이디어를 생성하고 프레젠테이션의 개요를 작성하거나 완벽한 시를 작성합니다.
Professional input: Boost productivity with idea feedback, note summarization, and technical topic assistance.
전문적인 입력: 아이디어 피드백, 메모 요약 및 기술 주제 지원을 통해 생산성을 높입니다.
Learning opportunities: Explore new languages, modern history, and more at your own pace.
학습 기회: 자신의 속도에 맞춰 새로운 언어, 현대사 등을 탐색하십시오.
We're starting our rollout in the US and will expand to additional countries in the coming weeks. We’re eager to see how you use the app. As we gather user feedback, we’re committed to continuous feature and safety improvements for ChatGPT.
우리는 미국에서 롤아웃을 시작하고 있으며 앞으로 몇 주 안에 더 많은 국가로 확장할 것입니다. 우리는 당신이 앱을 어떻게 사용하는지 보고 싶습니다. 사용자 피드백을 수집하면서 ChatGPT의 기능과 안전성을 지속적으로 개선하기 위해 최선을 다하고 있습니다.
With the ChatGPT app for iOS, we’re taking another step towardsour missionby transforming state-of-the-art research into useful tools that empower people, while continuously making them more accessible.
iOS용 ChatGPT 앱을 통해 우리는 최첨단 연구를 통해 사람들에게 힘을 실어주는 유용한 도구로 전환하고 지속적으로 접근할 수 있도록 함으로써 우리의 사명을 향한 또 다른 발걸음을 내딛고 있습니다.
P.S. Android users, you're next! ChatGPT will be coming to your devices soon.
추신 Android 사용자 여러분, 다음 차례입니다! ChatGPT가 곧 귀하의 기기에 제공될 예정입니다.
ChatGPT users can now turn off chat history, allowing you to choose which conversations can be used to train our models.
ChatGPT 사용자는 이제 채팅 기록을 끌 수 있으므로 모델 훈련에 사용할 수 있는 대화를 선택할 수 있습니다.
We've introduced the ability to turn off chat history in ChatGPT. Conversations that are started when chat history is disabled won’t be used to train and improve our models, and won’t appear in the history sidebar. These controls, which are rolling out to all users starting today, can be found in ChatGPT’s settings and can be changed at any time. We hope this provides an easier way to manage your data than our existing opt-out process. When chat history is disabled, we will retain new conversations for 30 days and review them only when needed to monitor for abuse, before permanently deleting.
ChatGPT에서 채팅 기록을 끄는 기능을 도입했습니다. 채팅 기록이 비활성화되었을 때 시작된 대화는 모델을 훈련 및 개선하는 데 사용되지 않으며 기록 사이드바에 표시되지 않습니다. 오늘부터 모든 사용자에게 배포되는 이러한 컨트롤은 ChatGPT의 설정에서 찾을 수 있으며 언제든지 변경할 수 있습니다. 이를 통해 기존의 옵트아웃 프로세스보다 데이터를 더 쉽게 관리할 수 있기를 바랍니다. 채팅 기록이 비활성화되면 새 대화를 30일 동안 보관하고 악용 여부를 모니터링해야 하는 경우에만 검토한 후 영구적으로 삭제합니다.
제가 따라 해 보니까 아래와 같은 순서로 진행이 되네요.
Click on ID (bottom Left) -> Data Controls -> Chat History & Training
We are also working on a new ChatGPT Business subscription for professionals who need more control over their data as well as enterprises seeking to manage their end users. ChatGPT Business will follow ourAPI’s data usage policies, which means that end users’ data won’t be used to train our models by default. We plan to make ChatGPT Business available in the coming months.
또한 데이터에 대한 더 많은 제어가 필요한 전문가와 최종 사용자를 관리하려는 기업을 위한 새로운 ChatGPT 비즈니스 구독을 위해 노력하고 있습니다. ChatGPT Business는 API의 데이터 사용 정책을 따르므로 최종 사용자의 데이터는 기본적으로 모델 교육에 사용되지 않습니다. 앞으로 몇 달 안에 ChatGPT 비즈니스를 제공할 계획입니다.
Finally, a new Export option in settings makes it much easier to export your ChatGPT data and understand what information ChatGPT stores. You’ll receive a file with your conversations and all other relevant data in email.
마지막으로 설정의 새로운 내보내기 옵션을 사용하면 ChatGPT 데이터를 훨씬 쉽게 내보내고 ChatGPT가 저장하는 정보를 이해할 수 있습니다. 대화 및 기타 모든 관련 데이터가 포함된 파일을 이메일로 받게 됩니다.
This initiative is essential to our commitment to develop safe and advanced AI. As we create technology and services that are secure, reliable, and trustworthy, we need your help.
이 이니셔티브는 안전하고 진보된 AI를 개발하려는 우리의 노력에 필수적입니다.안전하고 신뢰할 수 있으며 신뢰할 수 있는 기술과 서비스를 만들 때 귀하의 도움이 필요합니다.
OpenAI’s mission is to create artificial intelligence systems that benefit everyone. To that end, we invest heavily in research and engineering to ensure our AI systems are safe and secure. However, as with any complex technology, we understand that vulnerabilities and flaws can emerge.
OpenAI의 임무는 모두에게 도움이 되는 인공 지능 시스템을 만드는 것입니다.이를 위해 AI 시스템의 안전과 보안을 보장하기 위해 연구 및 엔지니어링에 막대한 투자를 하고 있습니다.그러나 모든 복잡한 기술과 마찬가지로 취약성과 결함이 나타날 수 있음을 이해합니다.
We believe that transparency and collaboration are crucial to addressing this reality. That’s why we are inviting the global community of security researchers, ethical hackers, and technology enthusiasts to help us identify and address vulnerabilities in our systems. We are excited to build on our coordinated disclosure commitments by offering incentives for qualifying vulnerability information. Your expertise and vigilance will have a direct impact on keeping our systems and users secure.
우리는 투명성과 협업이 이러한 현실을 해결하는 데 중요하다고 믿습니다.이것이 우리 시스템의 취약점을 식별하고 해결하는 데 도움을 줄 보안 연구원, 윤리적 해커 및 기술 애호가로 구성된 글로벌 커뮤니티를 초대하는 이유입니다.적격한 취약성 정보에 대한 인센티브를 제공함으로써 조정된 공개 공약을 구축하게 된 것을 기쁘게 생각합니다.귀하의 전문성과 경계는 시스템과 사용자를 안전하게 유지하는 데 직접적인 영향을 미칩니다.
Introducing the Bug Bounty Program
The OpenAI Bug Bounty Program is a way for us to recognize and reward the valuable insights of security researchers who contribute to keeping our technology and company secure. We invite you to report vulnerabilities, bugs, or security flaws you discover in our systems. By sharing your findings, you will play a crucial role in making our technology safer for everyone.
OpenAI Bug Bounty Program은 기술과 회사를 안전하게 유지하는 데 기여하는 보안 연구원의 귀중한 통찰력을 인정하고 보상하는 방법입니다.시스템에서 발견한 취약성, 버그 또는 보안 결함을 보고해 주시기 바랍니다.발견한 내용을 공유함으로써 모든 사람을 위해 기술을 더 안전하게 만드는 데 중요한 역할을 하게 됩니다.
We have partnered with Bugcrowd, a leading bug bounty platform, to manage the submission and reward process, which is designed to ensure a streamlined experience for all participants. Detailed guidelines and rules for participation can be found on ourBug Bounty Program page.
우리는 최고의 버그 바운티 플랫폼인 Bugcrowd와 협력하여 모든 참가자에게 간소화된 경험을 보장하도록 설계된 제출 및 보상 프로세스를 관리합니다.참여에 대한 자세한 지침과 규칙은 버그 바운티 프로그램 페이지에서 확인할 수 있습니다.
Incentives and rewards
To incentivize testing and as a token of our appreciation, we will be offering cash rewards based on the severity and impact of the reported issues. Our rewards range from $200 for low-severity findings to up to $20,000 for exceptional discoveries. We recognize the importance of your contributions and are committed to acknowledging your efforts.
테스트를 장려하고 감사의 표시로 보고된 문제의 심각성과 영향에 따라 현금 보상을 제공할 예정입니다.보상 범위는 심각도가 낮은 결과에 대한 $200부터 뛰어난 발견에 대한 최대 $20,000까지입니다.우리는 귀하의 기여의 중요성을 인식하고 귀하의 노력을 인정하기 위해 최선을 다하고 있습니다.
Staying secure together
At OpenAI, we recognize the critical importance of security and view it as a collaborative effort. We invite the security research community to participate in our Bug Bounty Program.
OpenAI에서는 보안의 중요성을 인식하고 이를 공동 작업으로 간주합니다.버그 바운티 프로그램에 보안 연구 커뮤니티를 초대합니다.
Interested in contributing further? We’re hiring—explore opensecurity roleson our careers page. Join us in ensuring that the frontier of technology is secure.
추가 기여에 관심이 있으십니까?채용 중입니다. 채용 페이지에서 열린 보안 역할을 살펴보세요.기술의 최전선이 안전한지 확인하는 데 저희와 함께하십시오.
Consider implementing rate limiting on the API endpoints you expose. While the current scale is limited, ChatGPT is widely used and you should expect a high volume of requests. You can monitor the number of requests and set limits accordingly.
노출하는 API 엔드포인트에서 rate limiting을 구현하는 것을 고려하십시오.현재 규모는 제한되어 있지만 ChatGPT는 널리 사용되며 많은 양의 요청을 예상해야 합니다.요청 수를 모니터링하고 그에 따라 제한을 설정할 수 있습니다.
Updating your plugin
After deploying your plugin to production, you might want to make changes to theai-plugin.jsonmanifest file. Currently, manifest files must be manually updated by going through the "Develop your own plugin" flow in the plugin store each time you make a change to the file.
플러그인을 프로덕션에 배포한 후 ai-plugin.json 매니페스트 파일을 변경할 수 있습니다.현재 매니페스트 파일은 파일을 변경할 때마다 플러그인 스토어에서 "Develop your own plugin" flow 를 통해 수동으로 업데이트해야 합니다.
ChatGPT will automatically fetch the latest OpenAPI spec each time a request is made.
ChatGPT는 요청이 있을 때마다 최신 OpenAPI 사양을 자동으로 가져옵니다.
Plugin terms
In order to register a plugin, you must agree to thePlugin Terms.
To ensure that plugins can only perform actions on resources that they control, OpenAI enforces requirements on the plugin's manifest and API specifications.
플러그인이 제어하는 리소스에서만 작업을 수행할 수 있도록 OpenAI는 플러그인의 매니페스트 및 API 사양에 대한 요구 사항을 적용합니다.
Defining the plugin's root domain
The manifest file defines information shown to the user (like logo and contact information) as well as a URL where the plugin's OpenAPI spec is hosted. When the manifest is fetched, the plugin's root domain is established following these rules:
매니페스트 파일은 사용자에게 표시되는 정보(예: 로고 및 연락처 정보)와 플러그인의 OpenAPI 사양이 호스팅되는 URL을 정의합니다.매니페스트를 가져오면 다음 규칙에 따라 플러그인의 루트 도메인이 설정됩니다.
If the domain haswww.as a subdomain, then the root domain will strip outwww.from the domain that hosts the manifest.
Subdomain 으로서 도메인에 www. 가 있으면 루트 도메인은 매니페스트를 호스트하는 도메인으로부터 www.를 제거할 것입니다.
Otherwise, the root domain is the same as the domain that hosts the manifest.
그렇지 않으면 루트 도메인은 매니페스트를 호스트하는 도메인과 같습니다.
Note on redirects: If there are any redirects in resolving the manifest, only child subdomain redirects are allowed. The only exception is following a redirect from a www subdomain to one without the www.
리디렉션에 대한 참고 사항: 매니페스트를 확인하는 데 리디렉션이 있는 경우 child subdomain 리디렉션만 허용됩니다.유일한 예외는 www 하위 도메인에서 www가 없는 도메인으로 리디렉션하는 경우입니다.
contact_info- The second-level domain of the email address should be the same as the second-level domain of the root domain.
contact_info - 이메일 주소의 2차 도메인은 루트 도메인의 2차 도메인과 동일해야 합니다.
Resolving the API spec
Theapi.urlfield in the manifest provides a link to an OpenAPI spec that defines APIs that the plugin can call into. OpenAPI allows specifying multipleserver base URLs. The following logic is used to select the server URL:
매니페스트의 api.url 필드는 플러그인이 호출할 수 있는 API를 정의하는 OpenAPI 사양에 대한 링크를 제공합니다.OpenAPI를 사용하면 여러 server base URLs을 지정할 수 있습니다.다음 논리는 서버 URL을 선택하는 데 사용됩니다.
Iterate through the list of server URLs
서버 URL 목록을 반복합니다.
Use the first server URL that is either an exact match of the root domain or a subdomain of the root domain
루트 도메인 또는 루트 도메인의 하위 도메인과 정확히 일치하는 첫 번째 서버 URL을 사용하십시오.
If neither cases above apply, then default to the domain where the API spec is hosted. For example, if the spec is hosted onapi.example.com, thenapi.example.comwill be used as the base URL for the routes in the OpenAPI spec.
위의 두 경우 모두 적용되지 않는 경우 API 사양이 호스팅되는 도메인으로 기본 설정됩니다.예를 들어 사양이 api.example.com에서 호스팅되는 경우 api.example.com은 OpenAPI 사양의 경로에 대한 기본 URL로 사용됩니다.
Note: Please avoid using redirects for hosting the API spec and any API endpoints, as it is not guaranteed that redirects will always be followed.
참고: 리디렉션이 항상 뒤따른다는 보장이 없으므로 API 사양 및 API 엔드포인트를 호스팅하기 위해 리디렉션을 사용하지 마십시오.
Use TLS and HTTPS
All traffic with the plugin (e.g., fetching theai-plugin.jsonfile, the OpenAPI spec, API calls) must use TLS 1.2 or later on port 443 with a valid public certificate.
플러그인이 있는 모든 트래픽(예: ai-plugin.json 파일 가져오기, OpenAPI 사양, API 호출)은 유효한 공개 인증서가 있는 포트 443에서 TLS 1.2 이상을 사용해야 합니다.
IP egress ranges
ChatGPT will call your plugin from an IP address in theCIDR block23.102.140.112/28. You may wish to explicitly allowlist these IP addresses.
ChatGPT는 CIDR 블록 23.102.140.112/28의 IP 주소에서 플러그인을 호출합니다.이러한 IP 주소를 명시적으로 허용 목록에 추가할 수 있습니다.
Separately, OpenAI's web browsing plugincrawls websitesfrom a different IP address block:23.98.142.176/28.
이와 별도로 OpenAI의 웹 브라우징 플러그인은 다른 IP 주소 블록(23.98.142.176/28)에서 웹사이트를 크롤링합니다.
FAQ
How is plugin data used?
Plugins connect ChatGPT to external apps. If a user enables a plugin, ChatGPT may send parts of their conversation and their country or state to your plugin.
플러그인은 ChatGPT를 외부 앱에 연결합니다.사용자가 플러그인을 활성화하면 ChatGPT는 대화의 일부와 국가 또는 주를 플러그인으로 보낼 수 있습니다.
What happens if a request to my API fails?
If an API request fails, the model might retry the request up to 10 times before letting the user know it cannot get a response from that plugin.
API 요청이 실패하면 모델은 해당 플러그인에서 응답을 받을 수 없음을 사용자에게 알리기 전에 요청을 최대 10번 재시도할 수 있습니다.
Can I invite people to try my plugin?
Yes, all unverified plugins can be installed by up to 15 users. At launch, only other developers with access will be able to install the plugin. We plan to expand access over time and will eventually roll out a process to submit your plugin for review before being made available to all users.
예, 확인되지 않은 모든 플러그인은 최대 15명의 사용자가 설치할 수 있습니다.출시 시 액세스 권한이 있는 다른 개발자만 플러그인을 설치할 수 있습니다.우리는 시간이 지남에 따라 액세스를 확장할 계획이며 궁극적으로 모든 사용자가 사용할 수 있게 되기 전에 검토를 위해 플러그인을 제출하는 프로세스를 출시할 것입니다.
To get started building, we are making available a set of simple plugins that cover different authentication schemas and use cases. From our simple no authentication todo list plugin to the morepowerful retrieval plugin, these examples provide a glimpse into what we hope to make possible with plugins.
building을 시작하기 위해 다양한 인증 스키마 및 사용 사례를 다루는 간단한 플러그인 세트를 제공하고 있습니다.단순한 no authentication todo list 플러그인에서 더 강력한 검색 플러그인에 이르기까지 이 예제는 플러그인으로 가능하게 하고자 하는 것을 엿볼 수 있는 기회를 제공합니다.
개발 중에 플러그인을 컴퓨터에서 로컬로 실행하거나 GitHub Codespaces, Replit 또는 CodeSandbox와 같은 클라우드 개발 환경을 통해 실행할 수 있습니다.
Learn how to build a simple todo list plugin with no auth
To start, define anai-plugin.jsonfile with the following fields:
시작하려면 다음 필드를 사용하여 ai-plugin.json 파일을 정의합니다.
{
"schema_version": "v1",
"name_for_human": "TODO Plugin (no auth)",
"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": "PLUGIN_HOSTNAME/openapi.yaml",
"is_user_authenticated": false
},
"logo_url": "PLUGIN_HOSTNAME/logo.png",
"contact_email": "support@example.com",
"legal_info_url": "https://example.com/legal"
}
Note thePLUGIN_HOSTNAMEshould be the actual hostname of your plugin server.
PLUGIN_HOSTNAME은 플러그인 서버의 실제 호스트 이름이어야 합니다.
Next, we can define the API endpoints to create, delete, and fetch todo list items for a specific user.
다음으로 특정 사용자에 대한 할 일 목록 항목을 생성, 삭제 및 가져오기 위해 API 끝점을 정의할 수 있습니다.
import json
import quart
import quart_cors
from quart import request
# Note: Setting CORS to allow chat.openapi.com is required for ChatGPT to access your 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()
Last, we need to set up and define a OpenAPI specification to match the endpoints defined on our local or remote server. You do not need to expose the full functionality of your API via the specification and can instead choose to let ChatGPT have access to only certain functionality.
마지막으로 로컬 또는 원격 서버에 정의된 엔드포인트와 일치하도록 OpenAPI 사양을 설정하고 정의해야 합니다.사양을 통해 API의 전체 기능을 노출할 필요는 없으며 대신 ChatGPT가 특정 기능에만 액세스하도록 선택할 수 있습니다.
There are also many tools that will automatically turn your server definition code into an OpenAPI specification so you don’t need to do it manually. In the case of the Python code above, the OpenAPI specification will look like:
서버 정의 코드를 OpenAPI 사양으로 자동 변환하여 수동으로 수행할 필요가 없도록 하는 많은 도구도 있습니다.위 Python 코드의 경우 OpenAPI 사양은 다음과 같습니다.
openapi: 3.0.1
info:
title: TODO Plugin
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'
servers:
- url: PLUGIN_HOSTNAME
paths:
/todos/{username}:
get:
operationId: getTodos
summary: Get the list of todos
parameters:
- in: path
name: username
schema:
type: string
required: true
description: The name of the user.
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/getTodosResponse'
post:
operationId: addTodo
summary: Add a todo to the list
parameters:
- in: path
name: username
schema:
type: string
required: true
description: The name of the user.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/addTodoRequest'
responses:
"200":
description: OK
delete:
operationId: deleteTodo
summary: Delete a todo from the list
parameters:
- in: path
name: username
schema:
type: string
required: true
description: The name of the user.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/deleteTodoRequest'
responses:
"200":
description: OK
components:
schemas:
getTodosResponse:
type: object
properties:
todos:
type: array
items:
type: string
description: The list of todos.
addTodoRequest:
type: object
required:
- todo
properties:
todo:
type: string
description: The todo to add to the list.
required: true
deleteTodoRequest:
type: object
required:
- todo_idx
properties:
todo_idx:
type: integer
description: The index of the todo to delete.
required: true
Learn how to build a simple todo list plugin with service level auth
To start, define anai-plugin.jsonfile with the following fields:
시작하려면 다음 필드를 사용하여 ai-plugin.json 파일을 정의합니다.
{
"schema_version": "v1",
"name_for_human": "TODO Plugin (service level auth)",
"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": "service_http",
"authorization_type": "bearer",
"verification_tokens": {
"openai": "758e9ef7984b415688972d749f8aa58e"
}
},
"api": {
"type": "openapi",
"url": "https://example.com/openapi.yaml",
"is_user_authenticated": false
},
"logo_url": "https://example.com/logo.png",
"contact_email": "support@example.com",
"legal_info_url": "https://example.com/legal"
}
Notice that the verification token is required for service level authentication plugins. The token is generated during the plugin installation process in the ChatGPT web UI.
서비스 수준 인증 플러그인에는 확인 토큰이 필요합니다.토큰은 ChatGPT 웹 UI에서 플러그인 설치 프로세스 중에 생성됩니다.
Next, we can define the API endpoints to create, delete, and fetch todo list items for a specific user. The endpoints also check that the user is authenticated.
다음으로 특정 사용자에 대한 할 일 목록 항목을 생성, 삭제 및 가져오기 위해 API 끝점을 정의할 수 있습니다.끝점은 또한 사용자가 인증되었는지 확인합니다.
import json
import quart
import quart_cors
from quart import request
# Note: Setting CORS to allow chat.openapi.com is required for ChatGPT to access your plugin
app = quart_cors.cors(quart.Quart(__name__), allow_origin="https://chat.openai.com")
_SERVICE_AUTH_KEY = "REPLACE_ME"
_TODOS = {}
def assert_auth_header(req):
assert req.headers.get(
"Authorization", None) == f"Bearer {_SERVICE_AUTH_KEY}"
@app.post("/todos/<string:username>")
async def add_todo(username):
assert_auth_header(quart.request)
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):
assert_auth_header(quart.request)
return quart.Response(response=json.dumps(_TODOS.get(username, [])), status=200)
@app.delete("/todos/<string:username>")
async def delete_todo(username):
assert_auth_header(quart.request)
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()
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=5002)
if __name__ == "__main__":
main()
Last, we need to set up and define a OpenAPI specification to match the endpoints defined on our local or remote server. In general, the OpenAPI specification would look the same regardless of the authentication method. Using an automatic OpenAPI generator will reduce the chance of errors when creating your OpenAPI specification so it is worth exploring the options.
마지막으로 로컬 또는 원격 서버에 정의된 엔드포인트와 일치하도록 OpenAPI 사양을 설정하고 정의해야 합니다.일반적으로 OpenAPI 사양은 인증 방법에 관계없이 동일하게 보입니다.자동 OpenAPI 생성기를 사용하면 OpenAPI 사양을 생성할 때 오류 가능성이 줄어들므로 옵션을 탐색해 볼 가치가 있습니다.
openapi: 3.0.1
info:
title: TODO Plugin
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'
servers:
- url: https://example.com
paths:
/todos/{username}:
get:
operationId: getTodos
summary: Get the list of todos
parameters:
- in: path
name: username
schema:
type: string
required: true
description: The name of the user.
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/getTodosResponse'
post:
operationId: addTodo
summary: Add a todo to the list
parameters:
- in: path
name: username
schema:
type: string
required: true
description: The name of the user.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/addTodoRequest'
responses:
"200":
description: OK
delete:
operationId: deleteTodo
summary: Delete a todo from the list
parameters:
- in: path
name: username
schema:
type: string
required: true
description: The name of the user.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/deleteTodoRequest'
responses:
"200":
description: OK
components:
schemas:
getTodosResponse:
type: object
properties:
todos:
type: array
items:
type: string
description: The list of todos.
addTodoRequest:
type: object
required:
- todo
properties:
todo:
type: string
description: The todo to add to the list.
required: true
deleteTodoRequest:
type: object
required:
- todo_idx
properties:
todo_idx:
type: integer
description: The index of the todo to delete.
required: true
Learn how to build a simple sports stats plugin
This plugin is an example of a simple sports stats API. Please keep in mind our domain policy and usage policies when considering what to build.
이 플러그인은 간단한 스포츠 통계 API의 예입니다.무엇을 구축할지 고려할 때 도메인 정책 및 사용 정책을 염두에 두십시오.
To start, define anai-plugin.jsonfile with the following fields:
시작하려면 다음 필드를 사용하여 ai-plugin.json 파일을 정의합니다.
{
"schema_version": "v1",
"name_for_human": "Sport Stats",
"name_for_model": "sportStats",
"description_for_human": "Get current and historical stats for sport players and games.",
"description_for_model": "Get current and historical stats for sport players and games. Always display results using markdown tables.",
"auth": {
"type": "none"
},
"api": {
"type": "openapi",
"url": "PLUGIN_HOSTNAME/openapi.yaml",
"is_user_authenticated": false
},
"logo_url": "PLUGIN_HOSTNAME/logo.png",
"contact_email": "support@example.com",
"legal_info_url": "https://example.com/legal"
}
Note thePLUGIN_HOSTNAMEshould be the actual hostname of your plugin server.
PLUGIN_HOSTNAME은 플러그인 서버의 실제 호스트 이름이어야 합니다.
Next, we define a mock API for a simple sports service plugin.
다음으로 간단한 스포츠 서비스 플러그인을 위한 모의 API를 정의합니다.
import json
import requests
import urllib.parse
import quart
import quart_cors
from quart import request
# Note: Setting CORS to allow chat.openapi.com is required for ChatGPT to access your plugin
app = quart_cors.cors(quart.Quart(__name__), allow_origin="https://chat.openai.com")
HOST_URL = "https://example.com"
@app.get("/players")
async def get_players():
query = request.args.get("query")
res = requests.get(
f"{HOST_URL}/api/v1/players?search={query}&page=0&per_page=100")
body = res.json()
return quart.Response(response=json.dumps(body), status=200)
@app.get("/teams")
async def get_teams():
res = requests.get(
"{HOST_URL}/api/v1/teams?page=0&per_page=100")
body = res.json()
return quart.Response(response=json.dumps(body), status=200)
@app.get("/games")
async def get_games():
query_params = [("page", "0")]
limit = request.args.get("limit")
query_params.append(("per_page", limit or "100"))
start_date = request.args.get("start_date")
if start_date:
query_params.append(("start_date", start_date))
end_date = request.args.get("end_date")
if end_date:
query_params.append(("end_date", end_date))
seasons = request.args.getlist("seasons")
for season in seasons:
query_params.append(("seasons[]", str(season)))
team_ids = request.args.getlist("team_ids")
for team_id in team_ids:
query_params.append(("team_ids[]", str(team_id)))
res = requests.get(
f"{HOST_URL}/api/v1/games?{urllib.parse.urlencode(query_params)}")
body = res.json()
return quart.Response(response=json.dumps(body), status=200)
@app.get("/stats")
async def get_stats():
query_params = [("page", "0")]
limit = request.args.get("limit")
query_params.append(("per_page", limit or "100"))
start_date = request.args.get("start_date")
if start_date:
query_params.append(("start_date", start_date))
end_date = request.args.get("end_date")
if end_date:
query_params.append(("end_date", end_date))
player_ids = request.args.getlist("player_ids")
for player_id in player_ids:
query_params.append(("player_ids[]", str(player_id)))
game_ids = request.args.getlist("game_ids")
for game_id in game_ids:
query_params.append(("game_ids[]", str(game_id)))
res = requests.get(
f"{HOST_URL}/api/v1/stats?{urllib.parse.urlencode(query_params)}")
body = res.json()
return quart.Response(response=json.dumps(body), status=200)
@app.get("/season_averages")
async def get_season_averages():
query_params = []
season = request.args.get("season")
if season:
query_params.append(("season", str(season)))
player_ids = request.args.getlist("player_ids")
for player_id in player_ids:
query_params.append(("player_ids[]", str(player_id)))
res = requests.get(
f"{HOST_URL}/api/v1/season_averages?{urllib.parse.urlencode(query_params)}")
body = res.json()
return quart.Response(response=json.dumps(body), 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=5001)
if __name__ == "__main__":
main()
Last, we define our OpenAPI specification:
마지막으로 OpenAPI 사양을 정의합니다.
openapi: 3.0.1
info:
title: Sport Stats
description: Get current and historical stats for sport players and games.
version: 'v1'
servers:
- url: PLUGIN_HOSTNAME
paths:
/players:
get:
operationId: getPlayers
summary: Retrieves all players from all seasons whose names match the query string.
parameters:
- in: query
name: query
schema:
type: string
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.
responses:
"200":
description: OK
/teams:
get:
operationId: getTeams
summary: Retrieves all teams for the current season.
responses:
"200":
description: OK
/games:
get:
operationId: getGames
summary: Retrieves all games that match the filters specified by the args. Display results using markdown tables.
parameters:
- in: query
name: limit
schema:
type: string
description: The max number of results to return.
- in: query
name: seasons
schema:
type: array
items:
type: string
description: Filter by seasons. Seasons are represented by the year they began. For example, 2018 represents season 2018-2019.
- in: query
name: team_ids
schema:
type: array
items:
type: string
description: Filter by team ids. Team ids can be determined using the getTeams function.
- in: query
name: start_date
schema:
type: string
description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or after this date.
- in: query
name: end_date
schema:
type: string
description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or before this date.
responses:
"200":
description: OK
/stats:
get:
operationId: getStats
summary: Retrieves stats that match the filters specified by the args. Display results using markdown tables.
parameters:
- in: query
name: limit
schema:
type: string
description: The max number of results to return.
- in: query
name: player_ids
schema:
type: array
items:
type: string
description: Filter by player ids. Player ids can be determined using the getPlayers function.
- in: query
name: game_ids
schema:
type: array
items:
type: string
description: Filter by game ids. Game ids can be determined using the getGames function.
- in: query
name: start_date
schema:
type: string
description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or after this date.
- in: query
name: end_date
schema:
type: string
description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or before this date.
responses:
"200":
description: OK
/season_averages:
get:
operationId: getSeasonAverages
summary: Retrieves regular season averages for the given players. Display results using markdown tables.
parameters:
- in: query
name: season
schema:
type: string
description: Defaults to the current season. A season is represented by the year it began. For example, 2018 represents season 2018-2019.
- in: query
name: player_ids
schema:
type: array
items:
type: string
description: Filter by player ids. Player ids can be determined using the getPlayers function.
responses:
"200":
description: OK
Learn how to build a semantic search and retrieval plugin
TheChatGPT retrieval pluginis a more fully featured code example. The scope of the plugin is large, so we encourage you to read through the code to see what a more advanced plugin looks like.
ChatGPT 검색 플러그인은 더 완전한 기능을 갖춘 코드 예제입니다.플러그인의 범위는 넓기 때문에 코드를 자세히 읽고 고급 플러그인이 어떻게 생겼는지 확인하는 것이 좋습니다.
Plugins offer numerous authentication schemas to accommodate various use cases. To specify the authentication schema for your plugin, use the manifest file. Ourplugin domain policyoutlines our strategy for addressing domain security issues. For examples of available authentication options, refer to theexamples section, which showcases all the different choices.
플러그인은 다양한 사용 사례를 수용하기 위해 수많은 인증 스키마를 제공합니다.플러그인에 대한 인증 스키마를 지정하려면 매니페스트 파일을 사용하십시오.플러그인 도메인 정책은 도메인 보안 문제를 해결하기 위한 전략을 간략하게 설명합니다.사용 가능한 인증 옵션의 예는 다양한 선택 사항을 보여주는 examples section을 참조하십시오.
No authentication
We support no-auth flow for applications that do not require authentication, where a user is able to send requests directly to your API without any restrictions. This is particularly useful if you have an open API that you want to make available to everyone, as it allows traffic from sources other than just OpenAI plugin requests.
사용자가 제한 없이 API에 직접 요청을 보낼 수 있는 인증이 필요하지 않은 애플리케이션에 대해 무인증 흐름을 지원합니다.이는 OpenAI 플러그인 요청 이외의 소스에서 트래픽을 허용하므로 모든 사람이 사용할 수 있게 하려는 개방형 API가 있는 경우에 특히 유용합니다.
"auth": {
"type": "none"
},
Service level
If you want to specifically enable OpenAI plugins to work with your API, you can provide a client secret during the plugin installation flow. This means that all traffic from OpenAI plugins will be authenticated but not on a user level. This flow benefits from a simple end user experience but less control from an API perspective.
OpenAI 플러그인이 API와 함께 작동하도록 구체적으로 활성화하려는 경우 플러그인 설치 흐름 중에 클라이언트 암호를 제공할 수 있습니다.이는 OpenAI 플러그인의 모든 트래픽이 인증되지만 사용자 수준에서는 인증되지 않음을 의미합니다.이 흐름은 단순한 최종 사용자 경험의 이점이 있지만 API 관점에서 제어력이 떨어집니다.
To start, a developer pastes in their access token (global key)
시작하려면 개발자가 액세스 토큰(글로벌 키)을 붙여넣습니다.
Then, they have to add the verification token to their manifest file
그런 다음 매니페스트 파일에 확인 토큰을 추가해야 합니다.
We store an encrypted version of the token
암호화된 버전의 토큰을 저장합니다.
Users don’t need to do anything when they install the plugin
사용자는 플러그인을 설치할 때 아무 것도 할 필요가 없습니다.
Last, we pass it in the Authorization header when making requests to the plugin (“Authorization”: “[Bearer/Basic][user’s token]”)
마지막으로 플러그인에 요청할 때 Authorization 헤더에 전달합니다("Authorization": "[Bearer/Basic][user's token]").
Just like how a user might already be using your API, we allow user level authentication through enabling end users to copy and paste their secret API key into the ChatGPT UI during plugin install. While we encrypt the secret key when we store it in our database, we do not recommend this approach given the poor user experience.
사용자가 이미 당신의 API를 사용하는 것처럼 최종 사용자가 플러그인 설치 중에 비밀 API 키를 복사하여 ChatGPT UI에 붙여넣을 수 있도록 하여 사용자 수준 인증을 허용합니다.비밀 키를 데이터베이스에 저장할 때 암호화하지만 사용자 경험이 좋지 않은 경우에는 이 접근 방식을 권장하지 않습니다.
To start, a user pastes in their access token when installing the plugin
시작하려면 사용자가 플러그인을 설치할 때 액세스 토큰을 붙여넣습니다.
We store an encrypted version of the token
암호화된 버전의 토큰을 저장합니다.
We then pass it in the Authorization header when making requests to the plugin (“Authorization”: “[Bearer/Basic][user’s token]”)
그런 다음 플러그인에 요청할 때 Authorization 헤더에 전달합니다("Authorization": "[Bearer/Basic][user's token]").
To better understand the URL structure for OAuth, here is a short description of the fields:
OAuth의 URL 구조를 더 잘 이해할 수 있도록 다음은 필드에 대한 간단한 설명입니다.
When you set up your plugin with ChatGPT, you will be asked to provide your OAuthclient_idandclient_secret
ChatGPT로 플러그인을 설정할 때 OAuth client_id 및 client_secret을 제공하라는 메시지가 표시됩니다.
When a user logs into the plugin, ChatGPT will direct the user’s browser to"[client_url]?response_type=code&client_id=[client_id]&scope=[scope]&redirect_uri=https%3A%2F%2Fchat.openai.com%2Faip%2F[plugin_id]%2Foauth%2Fcallback"
사용자가 플러그인에 로그인 할 때 챗GPT는 사용자의 브라우저를 이 페이지로 이동 시킬 겁니다. -> [client_url]?response_type=code&client_id=[client_id]&scope=[scope]&redirect_uri=https%3A%2F%2Fchat.openai.com%2Faip%2F[plugin_id]%2Foauth%2Fcallback
After your plugin redirects back to the given redirect_uri, ChatGPT will complete the OAuth flow by making a POST request toauthorization_urlwith content typeauthorization_content_typeand parameters{ “grant_type”: “authorization_code”, “client_id”: [client_id], “client_secret”: [client_secret], “code”: [the code that was returned with the redirect], “redirect_uri”: [the same redirect uri as before] }
플로그인이 주어진 redirect_uri 로 다시 redirection 된 후 챗GPT는 콘텐츠 요형 authorization_content_type 콘텐츠 유형 과 기타 파라미터들과 함께 authorization_url로 POST request를 만듦으로서 OAuth 흐름을 완료 하게 될 겁니다. 이때 사용되는 파라미터들은 다음과 같습니다. - authorization_content_typeand parameters{ “grant_type”: “authorization_code”, “client_id”: [client_id], “client_secret”: [client_secret], “code”: [the code that was returned with the redirect], “redirect_uri”: [the same redirect uri as before] }
Every plugin requires aai-plugin.jsonfile, which needs to be hosted on the API’s domain.
모든 플러그인에는 API 도메인에서 호스팅되어야 하는 ai-plugin.json 파일이 필요합니다.
For example, a company called example.com would make the plugin JSON file accessible via anhttps://example.comdomain since that is where their API is hosted.
예를 들어 example.com이라는 회사는 API가 호스팅되는 https://example.com 도메인을 통해 플러그인 JSON 파일에 액세스할 수 있도록 합니다.
When you install the plugin via the ChatGPT UI, on the backend we look for a file located at/.well-known/ai-plugin.json.
ChatGPT UI를 통해 플러그인을 설치하면 백엔드에서 /.well-known/ai-plugin.json에 있는 파일을 찾습니다.
The/.well-knownfolder is required and must exist on your domain in order for ChatGPT to connect with your plugin.
/.well-known 폴더가 필요하며 ChatGPT가 플러그인과 연결하려면 도메인에 있어야 합니다.
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.
파일이 없으면 플러그인을 설치할 수 없습니다. 로컬 개발의 경우 HTTP를 사용할 수 있지만 원격 서버를 가리키는 경우 HTTPS가 필요합니다.
The minimal definition of the requiredai-plugin.jsonfile will look like the following:
필요한 ai-plugin.json 파일의 최소 정의는 다음과 같습니다.
{
"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
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', }
The following are examples with different authentication methods:
다음은 인증 방법이 다른 예입니다.
# App-level API keys
type ManifestServiceHttpAuth = BaseManifestAuth & {
type: 'service_http';
authorization_type: HttpAuthorizationType;
verification_tokens: {
[service: string]?: string;
};
}
# User-level HTTP authentication
type ManifestUserHttpAuth = BaseManifestAuth & {
type: 'user_http';
authorization_type: HttpAuthorizationType;
}
type ManifestOAuthAuth = BaseManifestAuth & {
type: 'oauth';
# OAuth URL where a user is directed to for the OAuth authentication flow to begin.
client_url: string;
# OAuth scopes required to accomplish operations on the user's behalf.
scope: string;
# Endpoint used to exchange OAuth code with access token.
authorization_url: string;
# When exchanging OAuth code with access token, the expected header 'content-type'. For example: 'content-type: application/json'
authorization_content_type: string;
# When registering the OAuth client ID and secrets, the plugin service will surface a unique token.
verification_tokens: {
[service: string]?: string;
};
}
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 forname_for_human
name_for_human에 대해 최대 50자
50 character max forname_for_model
name_for_model은 최대 50자
120 character max fordescription_for_human
description_for_human은 최대 120자
8000 character max just fordescription_for_model(will decrease over time)
description_for_model의 경우 최대 8000자(시간이 지남에 따라 감소)
Separately, we also have a 100k character limit (will decrease over time) on the API response body length which is also subject to change.
이와는 별도로 API 응답 본문 길이에 대한 100,000자 제한(시간이 지남에 따라 줄어듦)도 변경될 수 있습니다.
The model in ChatGPT does not know anything about your API other than what is defined in the OpenAPI specification and manifest file.
ChatGPT의 모델은 OpenAPI 사양 및 매니페스트 파일에 정의된 것 외에는 API에 대해 아무것도 모릅니다.
This means that if you have an extensive API, you need not expose all functionality to the model and can choose specific endpoints.
즉, 광범위한 API가 있는 경우 모든 기능을 모델에 노출할 필요가 없으며 특정 엔드포인트를 선택할 수 있습니다.
For example, if you had 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.
예를 들어 소셜 미디어 API가 있는 경우 모델이 GET 요청을 통해 사이트의 콘텐츠에 액세스하도록 할 수 있지만 스팸 가능성을 줄이기 위해 모델이 사용자 게시물에 댓글을 달 수 없도록 할 수 있습니다.
The OpenAPI specification is the wrapper that sits on top of your API. A basic OpenAPI specification will look like the following:
OpenAPI 사양은 API 위에 있는 래퍼입니다.기본 OpenAPI 사양은 다음과 같습니다.
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.
ChatGPT에서 쿼리가 실행되면 정보 섹션에 정의된 설명을 보고 플러그인이 사용자 쿼리와 관련이 있는지 확인합니다.
Keep in mind the following limits in your OpenAPI specification, which are subject to change:
변경될 수 있는 OpenAPI 사양의 다음 제한에 유의하세요.
200 characters max for each API endpoint description/summary field in API specification
API 사양의 API 엔드포인트 설명/요약 필드당 최대 200자
200 characters max for each API param description field in API specification
API 사양의 각 API 매개변수 설명 필드에 대해 최대 200자
Since we are running this example locally, we want to set the server to point to your local host URL. The rest of the OpenAPI specification follows the traditional OpenAPI format, you canlearn more about OpenAPI formattingthrough various online resources. There are also many tools that auto generate OpenAPI specifications based on your underlying API code.
이 예제를 로컬에서 실행하고 있으므로 로컬 호스트 URL을 가리키도록 서버를 설정하려고 합니다.나머지 OpenAPI 사양은 기존 OpenAPI 형식을 따르므로 다양한 온라인 리소스를 통해 OpenAPI 형식에 대해 자세히 알아볼 수 있습니다.기본 API 코드를 기반으로 OpenAPI 사양을 자동으로 생성하는 많은 도구도 있습니다.
Running a plugin
Once you have created an API, manifest file, and OpenAPI specification for your API, you are now ready to connect the plugin via the ChatGPT UI. There are two different places your plugin might be running, either locally in a development environment or on a remote server.
API, 매니페스트 파일 및 API용 OpenAPI 사양을 생성했으면 이제 ChatGPT UI를 통해 플러그인을 연결할 준비가 된 것입니다.플러그인은 개발 환경의 로컬 또는 원격 서버의 두 가지 다른 위치에서 실행될 수 있습니다.
If you have a local version of your API running, you can point the plugin interface to that local setup. To connect the plugin with ChatGPT, you can navigate to the plugin store and then select “Install an unverified plugin”.
실행 중인 API의 로컬 버전이 있는 경우 플러그인 인터페이스가 해당 로컬 설정을 가리킬 수 있습니다.플러그인을 ChatGPT와 연결하려면 플러그인 스토어로 이동한 다음 "확인되지 않은 플러그인 설치"를 선택하면 됩니다.
If the plugin is running on a remote server, you will need to first select “Develop your own plugin” and then “Install an unverified plugin”.
플러그인이 원격 서버에서 실행 중인 경우 먼저 "자체 플러그인 개발"을 선택한 다음 "확인되지 않은 플러그인 설치"를 선택해야 합니다.
You can simply add the plugin manifest file to the ./well-known path and start testing your API.
플러그인 매니페스트 파일을 ./well-known 경로에 추가하고 API 테스트를 시작할 수 있습니다.
However, for subsequent changes to your manifest file, you will have to deploy the new changes to your public site which might take a long time. In that case, we suggest setting up a local server to act as a proxy for your API. This allows you to quickly prototype changes to your OpenAPI spec and manifest file.
이후에 매니페스트 파일을 변경하려면 새 변경 사항을 공개 사이트에 배포해야 하며 시간이 오래 걸릴 수 있습니다.이 경우 API의 프록시 역할을 하도록 로컬 서버를 설정하는 것이 좋습니다.이를 통해 OpenAPI 사양 및 매니페스트 파일에 대한 변경 사항의 프로토타입을 신속하게 만들 수 있습니다.
Setup a local proxy of your public API
The following Python code is an example of how you can set up a simple proxy of your public facing API.
다음 Python 코드는 공용 API의 간단한 프록시를 설정하는 방법의 예입니다.
import requests
import os
import yaml
from flask import Flask, jsonify, Response, request, send_from_directory
from flask_cors import CORS
app = Flask(__name__)
PORT = 3333
CORS(app, origins=[f"http://localhost:{PORT}", "https://chat.openai.com"])
api_url = 'https://example'
@app.route('/.well-known/ai-plugin.json')
def serve_manifest():
return send_from_directory(os.path.dirname(__file__), 'ai-plugin.json')
@app.route('/openapi.yaml')
def serve_openapi_yaml():
with open(os.path.join(os.path.dirname(__file__), 'openapi.yaml'), 'r') as f:
yaml_data = f.read()
yaml_data = yaml.load(yaml_data, Loader=yaml.FullLoader)
return jsonify(yaml_data)
@app.route('/openapi.json')
def serve_openapi_json():
return send_from_directory(os.path.dirname(__file__), 'openapi.json')
@app.route('/<path:path>', methods=['GET', 'POST'])
def wrapper(path):
headers = {
'Content-Type': 'application/json',
}
url = f'{api_url}/{path}'
print(f'Forwarding call: {request.method} {path} -> {url}')
if request.method == 'GET':
response = requests.get(url, headers=headers, params=request.args)
elif request.method == 'POST':
print(request.headers)
response = requests.post(url, headers=headers, params=request.args, json=request.json)
else:
raise NotImplementedError(f'Method {request.method} not implemented in wrapper for {path=}')
return response.content
if __name__ == '__main__':
app.run(port=PORT)
Writing descriptions
When a user makes a query that might be a potential request that goes to a plugin, the model looks through the descriptions of the endpoints in the OpenAPI specification along with thedescription_for_modelin the manifest file. Just like with prompting other language models, you will want to test out multiple prompts and descriptions to see what works best.
사용자가 플러그인으로 이동하는 잠재적인 요청일 수 있는 쿼리를 만들면 모델은 매니페스트 파일의 description_for_model과 함께 OpenAPI 사양의 엔드포인트 설명을 살펴봅니다.다른 언어 모델 프롬프트와 마찬가지로 여러 프롬프트와 설명을 테스트하여 무엇이 가장 잘 작동하는지 확인하고 싶을 것입니다.
The OpenAPI spec itself is a great place to give the model information about the diverse details of your API – what functions are available, with what parameters, etc. Besides using expressive, informative names for each field, the spec can also contain “description” fields for every attribute. These can be used to provide natural language descriptions of what a function does or what information a query field expects, for example. The model will be able to see these, and they will guide it in using the API. If a field is restricted to only certain values, you can also provide an “enum” with descriptive category names.
OpenAPI 사양 자체는 API의 다양한 세부 정보(사용 가능한 기능, 매개변수 등)에 대한 정보를 모델에 제공할 수 있는 좋은 장소입니다. 각 필드에 대해 표현적이고 유익한 이름을 사용하는 것 외에도 사양에는 "설명"도 포함될 수 있습니다.모든 속성에 대한 필드.예를 들어 함수가 수행하는 작업 또는 쿼리 필드에 필요한 정보에 대한 자연어 설명을 제공하는 데 사용할 수 있습니다.모델은 이를 볼 수 있으며 API를 사용하도록 안내합니다.필드가 특정 값으로만 제한되는 경우 설명 범주 이름과 함께 "enum"을 제공할 수도 있습니다.
The “description_for_model” attribute gives you the freedom to instruct the model on how to use your plugin generally. Overall, the language model behind ChatGPT is highly capable of understanding natural language and following instructions. Therefore, this is a good place to put in general instructions on what your plugin does and how the model should use it properly. Use natural language, preferably in a concise yet descriptive and objective tone. You can look at some of the examples to have an idea of what this should look like. We suggest starting thedescription_for_modelwith “Plugin for …” and then enumerating all of the functionality that your API provides.
"description_for_model" 속성은 일반적으로 플러그인을 사용하는 방법에 대해 모델에 지시할 수 있는 자유를 제공합니다.전반적으로 ChatGPT의 언어 모델은 자연어를 이해하고 지침을 따를 수 있는 능력이 뛰어납니다.따라서 플러그인이 수행하는 작업과 모델이 플러그인을 올바르게 사용하는 방법에 대한 일반적인 지침을 입력하기에 좋은 곳입니다.간결하면서도 설명적이고 객관적인 어조로 자연어를 사용하는 것이 좋습니다.몇 가지 예를 보면 이것이 어떤 모습이어야 하는지 알 수 있습니다.“Plugin for …”로 description_for_model을 시작한 다음 API가 제공하는 모든 기능을 열거하는 것이 좋습니다.
Best practices
Here are some best practices to follow when writing yourdescription_for_modeland descriptions in your OpenAPI specification, as well as when designing your API responses:
다음은 OpenAPI 사양에 description_for_model 및 설명을 작성할 때와 API 응답을 디자인할 때 따라야 할 몇 가지 모범 사례입니다.
Your descriptions should not attempt to control the mood, personality, or exact responses of ChatGPT. ChatGPT is designed to write appropriate responses to plugins.
귀하의 설명은 기분, 성격 또는 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]
Your descriptions should not encourage ChatGPT to use the plugin when the user hasn’t asked for your plugin’s particular category of service.
설명은 사용자가 플러그인의 특정 서비스 범주를 요청하지 않은 경우에도 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.
Your descriptions should not prescribe specific triggers for ChatGPT to use the plugin. ChatGPT is designed to use your plugin automatically when appropriate.
귀하의 설명은 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]
Plugin API responses should return raw data instead of natural language responses unless it’s necessary. ChatGPT will provide its own natural language response using the returned data.
플러그인 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" ]}
Debugging
By default, the chat will not show plugin calls and other information that is not surfaced to the user. In order to get a more complete picture of how the model is interacting with your plugin, you can see the request and response by clicking the down arrow on the plugin name after interacting with the plugin.
기본적으로 채팅에는 사용자에게 표시되지 않는 플러그인 호출 및 기타 정보가 표시되지 않습니다.모델이 플러그인과 상호 작용하는 방식을 보다 완벽하게 파악하기 위해 플러그인과 상호 작용한 후 플러그인 이름에서 아래쪽 화살표를 클릭하여 요청 및 응답을 볼 수 있습니다.
A model call to the plugin will usually consist of a message from the model (“Assistant”) containing JSON-like parameters which are sent to the plugin, followed by a response from the plugin (“Tool”), and finally a message from the model utilizing the information returned by the plugin.
플러그인에 대한 모델 호출은 일반적으로 플러그인으로 전송되는 JSON과 같은 매개변수를 포함하는 모델("Assistant")의 메시지, 플러그인("Tool")의 응답, 마지막으로플러그인이 반환한 정보를 활용하는 모델입니다.
In some cases, like during plugin installation, errors might be surfaced in the browsers javascript console.
플러그인 설치와 같은 경우에 브라우저의 javascript 콘솔에 오류가 표시될 수 있습니다.
We took ChatGPT offline earlier this week due to a bug in an open-source library which allowed some users to see titles from another active user’s chat history. It’s also possible that the first message of a newly-created conversation was visible in someone else’s chat history if both users were active around the same time.
일부 사용자가 다른 활성 사용자의 채팅 기록에서 제목을 볼 수 있도록 허용하는 오픈 소스 라이브러리의 버그로 인해 이번 주 초에 ChatGPT를 오프라인으로 전환했습니다.두 사용자가 거의 같은 시간에 활성화된 경우 새로 만든 대화의 첫 번째 메시지가 다른 사람의 채팅 기록에 표시되었을 수도 있습니다.
The bug is now patched. We were able to restore both the ChatGPT service and, later, its chat history feature, with the exception of a few hours of history. As promised, we’re publishing moretechnical detailsof this problem below.
이제 버그가 패치되었습니다.우리는 몇 시간의 기록을 제외하고 ChatGPT 서비스와 나중에 채팅 기록 기능을 모두 복원할 수 있었습니다.약속한 대로 이 문제에 대한 자세한 기술 정보를 아래에 게시하고 있습니다.
Upon deeper investigation, we also discovered that the same bug may have caused the unintentional visibility of payment-related information of 1.2% of the ChatGPT Plus subscribers who wereactiveduring a specific nine-hour window. In the hours before we took ChatGPT offline on Monday, it was possible for some users to see anotheractiveuser’s first and last name, email address, payment address, the last four digits (only) of a credit card number, and credit card expiration date. Full credit card numbers were not exposed at any time.
심층 조사 결과 동일한 버그로 인해 특정 9시간 동안 활성화된 ChatGPT Plus 가입자의 1.2%가 의도하지 않게 결제 관련 정보를 볼 수 있었던 것으로 나타났습니다.월요일에 ChatGPT를 오프라인으로 전환하기 몇 시간 전에 일부 사용자가 다른 활성 사용자의 이름과 성, 이메일 주소, 지불 주소, 신용 카드 번호의 마지막 4자리(만) 및 신용 카드 만료를 볼 수 있었습니다.날짜.전체 신용 카드 번호는 노출되지 않았습니다.
We believe the number of users whose data was actually revealed to someone else is extremely low. To access this information, a ChatGPT Plus subscriber would have needed to do one of the following:
실제로 다른 사람에게 데이터가 공개된 사용자의 수는 극히 적다고 생각합니다.이 정보에 액세스하려면 ChatGPT Plus 가입자가 다음 중 하나를 수행해야 합니다.
Open a subscription confirmation email sent on Monday, March 20, between 1 a.m. and 10 a.m. Pacific time. Due to the bug, some subscription confirmation emails generated during that window were sent to the wrong users. These emails contained the last four digits of another user’s credit card number, but full credit card numbers did not appear. It’s possible that a small number of subscription confirmation emails might have been incorrectly addressed prior to March 20, although we have not confirmed any instances of this.
태평양 표준시로 3월 20일 월요일 오전 1시에서 오전 10시 사이에 전송된 구독 확인 이메일을 엽니다.버그로 인해 해당 기간 동안 생성된 일부 구독 확인 이메일이 잘못된 사용자에게 전송되었습니다.이 이메일에는 다른 사용자의 신용 카드 번호의 마지막 4자리가 포함되어 있었지만 전체 신용 카드 번호는 나타나지 않았습니다.3월 20일 이전에 소수의 구독 확인 이메일 주소가 잘못 지정되었을 수 있지만 아직 확인된 바는 없습니다.
In ChatGPT, click on “My account,” then “Manage my subscription” between 1 a.m. and 10 a.m. Pacific time on Monday, March 20. During this window, anotheractiveChatGPT Plus user’s first and last name, email address, payment address, the last four digits (only) of a credit card number, and credit card expiration date might have been visible. It’s possible that this also could have occurred prior to March 20, although we have not confirmed any instances of this.
ChatGPT에서 3월 20일 월요일 오전 1시에서 오전 10시(태평양 표준시 기준) 사이에 "내 계정"을 클릭한 다음 "내 구독 관리"를 클릭합니다. 이 기간 동안 다른 활성 ChatGPT Plus 사용자의 성과 이름, 이메일 주소, 지불 주소,신용 카드 번호의 마지막 네 자리(만) 및 신용 카드 만료 날짜가 표시되었을 수 있습니다.3월 20일 이전에 이 일이 발생했을 가능성도 있지만 아직 확인된 바는 없습니다.
We have reached out to notify affected users that their payment information may have been exposed. We are confident that there is no ongoing risk to users’ data.
영향을 받는 사용자에게 결제 정보가 노출되었을 수 있음을 알리기 위해 연락했습니다.우리는 사용자 데이터에 대한 지속적인 위험이 없다고 확신합니다.
Everyone at OpenAI is committed to protecting our users’ privacy and keeping their data safe. It’s a responsibility we take incredibly seriously. Unfortunately, this week we fell short of that commitment, and of our users’ expectations. We apologize again to our users and to the entire ChatGPT community and will work diligently to rebuild trust.
OpenAI의 모든 사람은 사용자의 개인 정보를 보호하고 데이터를 안전하게 유지하기 위해 최선을 다하고 있습니다.그것은 우리가 믿을 수 없을 정도로 심각하게 생각하는 책임입니다.안타깝게도 이번 주에 우리는 그 약속과 사용자의 기대에 미치지 못했습니다.사용자와 전체 ChatGPT 커뮤니티에 다시 한 번 사과드리며 신뢰를 회복하기 위해 열심히 노력하겠습니다.
Technical details
The bug was discovered in the Redis client open-source library, redis-py. As soon as we identified the bug, we reached out to the Redis maintainers with a patch to resolve the issue. Here’s how the bug worked:
이 버그는 Redis 클라이언트 오픈 소스 라이브러리인 redis-py에서 발견되었습니다.버그를 확인하자마자 우리는 문제를 해결하기 위한 패치와 함께 Redis 관리자에게 연락했습니다.버그의 작동 방식은 다음과 같습니다.
We use Redis to cache user information in our server so we don’t need to check our database for every request.
Redis를 사용하여 서버의 사용자 정보를 캐시하므로 모든 요청에 대해 데이터베이스를 확인할 필요가 없습니다.
We use Redis Cluster to distribute this load over multiple Redis instances.
Redis 클러스터를 사용하여 이 로드를 여러 Redis 인스턴스에 분산합니다.
We use the redis-py library to interface with Redis from our Python server, which runs with Asyncio.
redis-py 라이브러리를 사용하여 Asyncio와 함께 실행되는 Python 서버에서 Redis와 인터페이스합니다.
The library maintains a shared pool of connections between the server and the cluster, and recycles a connection to be used for another request once done.
라이브러리는 서버와 클러스터 간의 연결 공유 풀을 유지 관리하고 완료되면 다른 요청에 사용할 연결을 재활용합니다.
When using Asyncio, requests and responses with redis-py behave as two queues: the caller pushes a request onto the incoming queue, and will pop a response from the outgoing queue, and then return the connection to the pool.
Asyncio를 사용할 때 redis-py를 사용한 요청 및 응답은 두 개의 대기열로 작동합니다. 호출자는 요청을 수신 대기열에 푸시하고 발신 대기열에서 응답을 팝한 다음 연결을 풀로 반환합니다.
If a request is canceled after the request is pushed onto the incoming queue, but before the response popped from the outgoing queue, we see our bug: the connection thus becomes corrupted and the next response that’s dequeued for an unrelated request can receive data left behind in the connection.
만약 요청이 incoming queue에 푸시된 후 요청이 취소되었고 outgoing queue에서 응답이 팝되기 전, 그 사이에서 버그가 나타납니다. 따라서 connection은 손상이 되고 다음 response 가 관련 없는 request와 dequeued 됨으로서 그 connection에 그대로 남은 데이터를 받을 수 있게 되는 겁니다.
In most cases, this results in an unrecoverable server error, and the user will have to try their request again.
대부분의 경우 이로 인해 unrecoverable server error가 발생하고 사용자는 request 를 다시 시도해야 합니다.
But in some cases the corrupted data happens to match the data type the requester was expecting, and so what gets returned from the cache appears valid, even if it belongs to another user.
그러나 경우에 따라 손상된 데이터 타입이 요청자가 기대하고 있는 데이터 타입과 일치하게 되고 그로 인해서 cache에 반환된 데이터가 다른 사용자에 속해 있는 데이터 임에도 불구하고 유효한 것으로 나타납니다.
At 1 a.m. Pacific time on Monday, March 20, we inadvertently introduced a change to our server that caused a spike in Redis request cancellations. This created a small probability for each connection to return bad data.
3월 20일 월요일 오전 1시(태평양 표준시)에 우리는 실수로 Redis request cancellations 급증을 초래하는 변경을 서버에 행했습니다.이로 인해 각 연결이 잘못된 데이터를 반환할 가능성이 적습니다. 이 변경으로 인해 각 연결들은 잘못된 데이터를 return 할 가능성이 더 줄어 들었습니다.
This bug only appeared in the Asyncio redis-py client for Redis Cluster, and has now been fixed.
이 버그는 Redis Cluster용 Asyncio redis-py 클라이언트에서만 나타났으며 이제 수정되었습니다.
Actions we’ve taken
As our investigation wraps up, supporting and informing our users is our top priority.
조사가 마무리됨에 따라 이제 사용자를 지원하고 알리는 것이 우리의 최우선 과제입니다.
We have taken the following actions to improve our systems:
시스템 개선을 위해 다음과 같은 조치를 취했습니다.
Extensively tested our fix to the underlying bug.
기본 버그에 대한 수정 사항을 광범위하게 테스트했습니다.
Added redundant checks to ensure the data returned by our Redis cache matches the requesting user.
Redis 캐시에서 반환된 데이터가 요청한 사용자와 일치하는지 확인하기 위해 중복 검사를 추가했습니다.
Programatically examined our logs to make sure that all messages are only available to the correct user.
모든 메시지가 올바른 사용자에게만 제공되는지 확인하기 위해 프로그래밍 방식으로 로그를 검사했습니다.
Correlated several data sources to precisely identify the affected users so that we can notify them.
영향을 받는 사용자를 정확하게 식별하여 알릴 수 있도록 여러 데이터 소스를 연관시켰습니다.
Improved logging to identify when this is happening and fully confirm it has stopped.
이러한 일이 발생하는 시기를 식별하고 중지되었는지 완전히 확인하기 위해 로깅이 개선되었습니다.
Improved the robustness and scale of our Redis cluster to reduce the likelihood of connection errors at extreme load.
Redis 클러스터의 견고성과 규모를 개선하여 극한 부하에서 연결 오류 가능성을 줄였습니다.
Where we go from here
The Redis open-source maintainers have been fantastic collaborators, swiftly addressing the bug and rolling out a patch.
Redis 오픈 소스 유지 관리자는 버그를 신속하게 해결하고 패치를 출시하는 환상적인 협력자였습니다.
Redis, along with other open-source software, plays a crucial role in our research efforts. Their significance cannot be understated—we would not have been able to scale ChatGPT without Redis.
Redis는 다른 오픈 소스 소프트웨어와 함께 우리의 연구 노력에서 중요한 역할을 합니다.Redis가 없었다면 ChatGPT를 확장할 수 없었을 것입니다.
We’re dedicated to continually supporting and contributing to the Redis community.
제목에서는 GPT-4 가 Open AI의 가장 진보된 시스템이고 더 안전하고 유용한 답변을 한다고 돼 있습니다.
이 GPT-4 API를 사용하려면 API waitlist에 등록 해야 합니다.
GPT-4는 폭넓은 일반 지식과 문제 해결 능력 덕분에 어려운 문제를 더 정확하게 풀 수 있습니다.
라고 말을 하고 있고 그 아래 GPT-4에서 개선 된 부분들에 대해 나옵니다.
우선 Creativity와 Visual input 그리고 Longer context 이렇게 3개의 탭이 있습니다.
Creativity 부터 볼까요?
GPT4 is more creative and collaborative than ever before. It can generate, edit, and iterate with users on creative and technical writing tasks, such as composing songs, writing screenplays, or learning a user’s writing style.
GPT-4는 그 어느 때보다 창의적이고 협력적입니다. 노래 작곡, 시나리오 작성 또는 사용자의 작문 스타일 학습과 같은 창의적이고 기술적인 작문 작업에서 사용자와 함께 생성, 편집 및 반복할 수 있습니다.
Input Explain the plot of Cinderella in a sentence where each word has to begin with the next letter in the alphabet from A to Z, without repeating any letters.
Output A beautiful Cinderella, dwelling eagerly, finally gains happiness; inspiring jealous kin, love magically nurtures opulent prince; quietly rescues, slipper triumphs, uniting very wondrously, xenial youth zealously.
input으로 아래와 같은 요구를 했습니다.
문자를 반복하지 않고 A부터 Z까지 알파벳의 다음 문자로 각 단어가 시작되어야 하는 문장으로 신데렐라의 줄거리를 설명합니다.
그랬더니 신데렐라의 줄거리를 진짜 A 부터 Z까지 시작하는 단어들을 차례대로 사용해서 설명을 했습니다.
두번째는 Visual input 분야 입니다.
이미지 파일을 주고 이 재료들을 가지고 무엇을 만들 수 있냐고 물었더니...
Output There are many options for what you can make with these ingredients! Some possibilities include:
- Pancakes or waffles - Crepes - French toast - Omelette or frittata - Quiche - Custard or pudding - Cake or cupcakes - Muffins or bread- Cookies or biscuits
These are just a few examples, but the possibilities are endless! few examples, but the possibilities are endless!
이런 답변을 했네요. 그림만 보고 그 안에 있는 재료들을 판단해서 거기에 맞는 가능한 요리들을 보여 줬습니다.
그 다음은 아주 긴 input 값을 받을 수 있다는 내용입니다.
GPT-4 is capable of handling over 25,000 words of text, allowing for use cases like long form content creation, extended conversations, and document search and analysis.
GPT-4는 25,000단어 이상의 텍스트를 처리할 수 있어 긴 형식의 콘텐츠 생성, 확장된 대화, 문서 검색 및 분석과 같은 사용 사례를 허용합니다.
예제로는 리하나의 위키피디아의 내용을 입력값으로 주고 이번 Super Bowl 공연에 대해 물어보고 GPT-4 가 대답하는 내용이 있습니다.
그 다음에는 GPT-4 는 작년 말에 발표 되서 센세이션을 일으켰던 ChatGPT 보다 더 성능이 좋다는 내용이 있습니다.
Uniform Bar Exam 과 Biology Olympiad 라는 테스트 경진 대회에서 GPT-4 가 ChatGPT 보다 더 높은 점수를 기록했다는 내용 입니다.
참고로 ChatGPT는 GPT-3.5 버전입니다.
밑의 설명은 GPT가 버전 2, 3, 3.5, 4 이렇게 진행돼 오면서 점점 더 정교하고 유능한 모델이 되어 가고 있다는 내용입니다.
We spent 6 months making GPT-4 safer and more aligned. GPT4 is 82% less likely to respond to requests for disallowed content and 40% more likely to produce factual responses than GPT-3.5 on our internal evaluations.
우리는 6개월 동안 GPT-4를 더 안전하고 더 잘 정렬되도록 만들었습니다. GPT-4는 허용되지 않는 콘텐츠에 대한 요청에 응답할 가능성이 82% 적고 내부 평가에서 GPT-3.5보다 사실에 입각한 응답을 할 가능성이 40% 더 높습니다.
Safety & alignment
Training with human feedback We incorporated more human feedback, including feedback submitted by ChatGPT users, to improve GPT-4’s behavior. We also worked with over 50 experts for early feedback in domains including AI safety and security.
GPT-4의 동작을 개선하기 위해 ChatGPT 사용자가 제출한 피드백을 포함하여 더 많은 사람의 피드백을 통합했습니다. 또한 AI 안전 및 보안을 포함한 도메인의 초기 피드백을 위해 50명 이상의 전문가와 협력했습니다.
Continuous improvement from real-world use We’ve applied lessons from real-world use of our previous models into GPT-4’s safety research and monitoring system. Like ChatGPT, we’ll be updating and improving GPT-4 at a regular cadence as more people use it.
우리는 이전 모델의 실제 사용에서 얻은 교훈을 GPT-4의 안전 연구 및 모니터링 시스템에 적용했습니다. ChatGPT와 마찬가지로 더 많은 사람들이 사용함에 따라 정기적으로 GPT-4를 업데이트하고 개선할 것입니다.
GPT-4-assisted safety research GPT-4’s advanced reasoning and instruction-following capabilities expedited our safety work. We used GPT-4 to help create training data for model fine-tuning and iterate on classifiers across training, evaluations, and monitoring.
GPT-4의 고급 추론 및 지시에 따른 기능은 우리의 안전 작업을 가속화했습니다. GPT-4를 사용하여 모델 미세 조정을 위한 훈련 데이터를 생성하고 훈련, 평가 및 모니터링 전반에 걸쳐 분류기를 반복했습니다.
그 다음 아래 부터는 실제 이 GPT-4를 사용해서 제품을 생산 판매 하고 있는 회사와 그 제품을 나열 했습니다.
GPT-4는 Microsoft Azure AI 슈퍼컴퓨터에서 교육을 받았습니다. Azure의 AI 최적화 인프라를 통해 전 세계 사용자에게 GPT-4를 제공할 수도 있습니다.
Limitations
GPT-4에는 사회적 편견, 환각, 적대적 프롬프트와 같이 우리가 해결하기 위해 노력하고 있는 많은 알려진 한계가 있습니다. 우리는 사회가 이러한 모델을 채택함에 따라 투명성, 사용자 교육 및 광범위한 AI 활용 능력을 장려하고 촉진합니다. 우리는 또한 우리 모델을 형성하는 데 사람들이 입력할 수 있는 방법을 확장하는 것을 목표로 합니다.
Availability
GPT-4는 ChatGPT Plus에서 사용할 수 있으며 개발자가 애플리케이션 및 서비스를 구축하기 위한 API로 사용할 수 있습니다.
이 가이드는 채팅 기반 언어 모델에 대한 API 호출을 만드는 방법을 설명하고 좋은 결과를 얻기 위한 팁을 공유합니다.
여러분은 또한 OpenAI Playground에서 채로운 채팅 형식을 실험해 볼 수도 있습니다.
Introduction
Chat models take a series of messages as input, and return a model-generated message as output.
채팅 모델은 일련의 메세지를 입력값으로 받고 모델이 생성한 메세지를 output 으로 반환합니다.
Although the chat format is designed to make multi-turn conversations easy, it’s just as useful for single-turn tasks without any conversations (such as those previously served by instruction following models liketext-davinci-003).
채팅 형식은 multi-turn 대화를 쉽게 할 수 있도록 디자인 되었지만 대화가 없는 Single-turn 작업에도 유용하게 사용할 수 있습니다. (예: text-davinci-003 같이 instruction 에 따르는 모델이 제공한 것 같은 서비스)
An example API call looks as follows: 예제 API 호출은 아래와 같습니다.
# Note: you need to be using OpenAI Python v0.27.0 for the code below to work
import openai
openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Who won the world series in 2020?"},
{"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."},
{"role": "user", "content": "Where was it played?"}
]
)
openai를 import 한 다음 openai.ChatCompletion.create() API 를 사용하면 됩니다.
The main input is the messages parameter. Messages must be an array of message objects, where each object has a role (either “system”, “user”, or “assistant”) and content (the content of the message). Conversations can be as short as 1 message or fill many pages.
주요 입력값들은 메세지의 파라미터 들입니다. 메세지들은 반드시 메세지 객체의 배열 형식이어야 합니다. 각 객체들에는 Role (역할) 이 주어집니다. (System, User, 혹은 Assistant 가 해당 메세지 객체의 Role이 됩니다.) 그리고 내용이 있습니다. (그 내용은 메세지가 됩니다.) 대화는 1개의 메세지로 된 짧은 형식이 될 수도 있고 여러 페이지에 걸친 많은 양이 될 수도 있습니다.
Typically, a conversation is formatted with a system message first, followed by alternating user and assistant messages.
일반적으로 대화는 먼저 System 메세지로 틀을 잡고 다음에 User와 Assistant 메세지가 번갈이 표시되게 됩니다.
The system message helps set the behavior of the assistant. In the example above, the assistant was instructed with “You are a helpful assistant.”
System 메세지는 Assistant의 행동을 설정하는데 도움이 됩니다. 위에 메세지에서 System 메세지는 Assistant에게 "당신은 도움을 주는 도우미 입니다" 라고 설정을 해 줬습니다.
The user messages help instruct the assistant. They can be generated by the end users of an application, or set by a developer as an instruction.
User 메세지는 Assistant에게 instruct (지시) 하도록 도와 줍니다. 이 메세지는 해당 어플리케이션의 사용자가 생성하게 됩니다. 혹은 개발자가 instruction으로서 생성하게 될 수도 있습니다.
The assistant messages help store prior responses. They can also be written by a developer to help give examples of desired behavior.
Assistant 메세지는 prior responses를 저장하는데 도움을 줍니다. 이 메세지도 개발자가 작성할 수 있습니다. gpt-3.5-turbo 모델이 어떤 식으로 응대할지에 대한 예를 제공합니다. (캐주얼하게 작성을 하면 ChatAPI 모델은 그것에 맞게 캐주얼한 형식으로 답변을 제공하고 formal 하게 제시하면 그 모델은 그에 맞게 formal 한 형식으로 답변을 제공할 것입니다.)
Including the conversation history helps when user instructions refer to prior messages. In the example above, the user’s final question of “Where was it played?” only makes sense in the context of the prior messages about the World Series of 2020. Because the models have no memory of past requests, all relevant information must be supplied via the conversation. If a conversation cannot fit within the model’s token limit, it will need to be shortened in some way.
이미 오고간 대화들을 제공하면 user 가 instruction을 제공하기 이전의 메세지로서 참조가 됩니다. 즉 그 대화의 분위기나 형식에 맞는 응답을 받게 될 것입니다. 위의 에에서 user의 마지막 질문은 "Where was it played?" 입니다.
이전의 대화들이 있어야지만이 이 질문이 무엇을 의미하는지 알 수 있습니다. 이전의 대화들이 2020년 월드 시리즈에 대한 내용들이었기 때문에 이 질문의 의미는 2020년 월드 시리즈는 어디에서 개최 됐느냐는 질문으로 모델을 알아 듣게 됩니다.
이 모델은 과거 request들에 대한 기억이 없기 때문에 이런 식으로 관련 정보를 제공합니다.
Request에는 모델별로 사용할 수 있는 Token 수가 정해져 있습니다. Request가 이 Token 수를 초과하지 않도록 작성해야 합니다.
Response format
이 API의 response는 아래와 같은 형식입니다.
{
'id': 'chatcmpl-6p9XYPYSTTRi0xEviKjjilqrWU2Ve',
'object': 'chat.completion',
'created': 1677649420,
'model': 'gpt-3.5-turbo',
'usage': {'prompt_tokens': 56, 'completion_tokens': 31, 'total_tokens': 87},
'choices': [
{
'message': {
'role': 'assistant',
'content': 'The 2020 World Series was played in Arlington, Texas at the Globe Life Field, which was the new home stadium for the Texas Rangers.'},
'finish_reason': 'stop',
'index': 0
}
]
}
파이썬에서 assistant의 응답은 다음과 같은 방법으로 추출 될 수 있습니다.
response[‘choices’][0][‘message’][‘content’]
Managing tokens
Language models read text in chunks called tokens. In English, a token can be as short as one character or as long as one word (e.g.,aorapple), and in some languages tokens can be even shorter than one character or even longer than one word.
Language 모델은 토큰이라는 chunk로 텍스트를 읽습니다. 영어에서 토큰은 글자 하나인 경우도 있고 단어 하나인 경우도 있습니다. (예. a 혹은 apple). 영어 이외의 다른 언어에서는 토큰이 글자 하나보다 짧거나 단어 하나보다 길 수도 있습니다.
For example, the string“ChatGPT is great!”is encoded into six tokens:[“Chat”, “G”, “PT”, “ is”, “ great”, “!”].
예를 들어 ChatGPT is great! 이라는 문장은 다음과 같이 6개의 토큰으로 구성됩니다. [“Chat”, “G”, “PT”, “ is”, “ great”, “!”]
The total number of tokens in an API call affects: How much your API call costs, as you pay per token How long your API call takes, as writing more tokens takes more time Whether your API call works at all, as total tokens must be below the model’s maximum limit (4096 tokens forgpt-3.5-turbo-0301)
APPI 호출의 총 토큰수는 다음과 같은 사항들에 영향을 미칩니다. : 해당 API 호출에 얼마가 과금이 될지 여부. 대개 1000개의 토큰당 요금이 과금이 되기 때문에 토큰이 아주 길면 그만큼 과금이 더 될 수 있습니다. 이는 토큰이 많을 수록 API 호출을 처리하는데 시간이 더 걸리기 때문이죠. request의 전체 토큰 수는 제한량을 넘을 수 없습니다. (gpt-3.5-turbo-0301 의 경우 4096 개의 토큰이 제한량입니다.)
Both input and output tokens count toward these quantities. For example, if your API call used 10 tokens in the message input and you received 20 tokens in the message output, you would be billed for 30 tokens.
입력 및 출력 토큰 모두 해당 호출의 토큰수에 포함됩니다. 예를 들어 API 호출에서 입력값으로 10개의 토큰을 사용했고 output으로 20개의 토큰을 받을 경우 30개의 토큰에 대해 과금 됩니다.
To see how many tokens are used by an API call, check theusagefield in the API response (e.g.,response[‘usage’][‘total_tokens’]).
API 호출에서 사용되는 토큰의 수를 확인 하려면 API response 중 usage 필드를 확인하시면 됩니다. (e.g., response[‘usage’][‘total_tokens’]).
To see how many tokens are in a text string without making an API call, use OpenAI’stiktokenPython library. Example code can be found in the OpenAI Cookbook’s guide onhow to count tokens with tiktoken.
Each message passed to the API consumes the number of tokens in the content, role, and other fields, plus a few extra for behind-the-scenes formatting. This may change slightly in the future.
API에 전달된 각각의 메세지는 content, role 그리고 다른 필드들에서 토큰이 소비 됩니다. 그리고 이런 필드들 이외에도 서식관련 해서 공간을 사용해야 하기 때문에 토큰이 소비 되는 부분도 있습니다. 자세한 사항들은 차후에 변경될 수도 있습니다.
If a conversation has too many tokens to fit within a model’s maximum limit (e.g., more than 4096 tokens forgpt-3.5-turbo), you will have to truncate, omit, or otherwise shrink your text until it fits. Beware that if a message is removed from the messages input, the model will lose all knowledge of it.
대화에 토큰이 너무 많이 모델의 허용 한도 이내에서 작성할 수 없을 경우 (예: gpt-3.5-turbo의 경우 4096개가 제한량임) 그 한도수 이내가 될 때까지 자르거나 생략하거나 축소해야 합니다. message 입력값에서 message 부분이 제한량 초과로 날아가 버리면 모델은 이에 대한 모든 knowledge들을 잃게 됩니다.
Note too that very long conversations are more likely to receive incomplete replies. For example, agpt-3.5-turboconversation that is 4090 tokens long will have its reply cut off after just 6 tokens.
매우 긴 대화는 불완전한 답변을 받을 가능성이 더 높습니다. 이점에 유의하세요. 예를 들어 gpt-3.5-turbo 의 대화에 4090개의 토큰이 입력값에서 사용됐다면 출력값으로는 6개의 토큰만 받고 그 나무지는 잘려 나갑니다.
Instructing chat models
Best practices for instructing models may change from model version to version. The advice that follows applies to gpt-3.5-turbo-0301 and may not apply to future models.
모델에 instructing 하는 가장 좋은 방법은 모델의 버전마다 다를 수 있습니다. 다음에 나오는 내용은 gpt-3.5-turbo-0301 버전에 적용됩니다. 그 이후의 모델에는 적용될 수도 있고 적용되지 않을 수도 있습니다.
Many conversations begin with a system message to gently instruct the assistant. For example, here is one of the system messages used for ChatGPT:
assistant에게 젠틀하게 지시하는 system 메세지로 많은 대화들을 시작하세요. 예를 들어 ChatGPT에서 사용되는 시스템 메세지 중 하나를 아래에 보여드리겠습니다.
You are ChatGPT, a large language model trained by OpenAI. Answer as concisely as possible. Knowledge cutoff: {knowledge_cutoff} Current date: {current_date}
In general,gpt-3.5-turbo-0301does not pay strong attention to the system message, and therefore important instructions are often better placed in a user message.
일반적으로 gpt-3.5-turbo-0301은 System 메세지의 크게 주의를 기울이지 않으므로 핵심 instruction은 User 메세지에 주로 배치 됩니다.
If the model isn’t generating the output you want, feel free to iterate and experiment with potential improvements. You can try approaches like:
모델의 output 이 원하는 대로 안 나오면 잠재적인 개선을 이끌수 있는 반복과 실험을 하는데 주저하지 마세요. 예를 들어 아래와 같이 접근 할 수 있습니다.
Make your instruction more explicit
명료하게 지시를 하세요.
Specify the format you want the answer in
응답을 받고자 하는 형식을 특정해 주세요.
Ask the model to think step by step or debate pros and cons before settling on an answer
모델이 최종 답을 결정하기 전에 단계별로 생각하거나 장단넘에 대해 debate을 해 보라고 요청하세요.
Beyond the system message, the temperature and max tokens aretwo of many optionsdevelopers have to influence the output of the chat models. For temperature, higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. In the case of max tokens, if you want to limit a response to a certain length, max tokens can be set to an arbitrary number. This may cause issues for example if you set the max tokens value to 5 since the output will be cut-off and the result will not make sense to users.
System 메세지 이외에도 temperature와 max token은 채팅 모델의 output에 영향을 주는 많은 옵션 중 두가지 옵션 입니다.
Temperature의 경우 0.8 이상의 값은 output을 더 random 하게 만듭니다. 그보다 값이 낮으면 예를 들어 0.2 뭐 이렇게 되면 더 focused 하고 deterministic 한 답변을 내 놓습니다. max token의 경우 여러분이 답변을 특정 길이로 제한하고 싶을 때 이 max token을 임의의 숫자로 세팅할 수 있습니다. 이것을 사용할 때는 주의하셔야 합니다. 예를 들어 최대 토큰 값을 5처럼 아주 낮게 설정하면 output이 잘리고 사용자에게 의미가 없을 수 있기 때문에 문제가 발생할 수 있습니다.
Chat vs Completions
Becausegpt-3.5-turboperforms at a similar capability totext-davinci-003but at 10% the price per token, we recommendgpt-3.5-turbofor most use cases.
gpt-3.5-turbo는 text-davinci-003과 비슷한 성능을 보이지만 토큰당 가격은 10% 밖에 하지 않습니다. 그렇기 때문에 우리는 대부분의 사용 사례에 gpt-3.5-turbo를 사용할 것을 권장합니다.
For many developers, the transition is as simple as rewriting and retesting a prompt.
많은 개발자들에게 transition은 프롬프트를 rewriting 하고 retesting 하는 것 만큼 아주 간단합니다.
For example, if you translated English to French with the following completions prompt:
예를 들어 여러분이 영어를 불어로 아래와 같이 completions prompt로 번역한다면,
Translate the following English text to French: “{text}”
이 채팅 모델로는 아래와 같이 할 수 있습니다.
[
{“role”: “system”, “content”: “You are a helpful assistant that translates English to French.”},
{“role”: “user”, “content”: ‘Translate the following English text to French: “{text}”’}
]
혹은 이렇게 user 메세지만 주어도 됩니다.
[
{“role”: “user”, “content”: ‘Translate the following English text to French: “{text}”’}
]
FAQ
Is fine-tuning available forgpt-3.5-turbo?
gpt-3.5-turbo에서도 fine-tuning이 가능한가요?
No. As of Mar 1, 2023, you can only fine-tune base GPT-3 models. See thefine-tuning guidefor more details on how to use fine-tuned models.
아니오. 2023년 3월 1일 현재 GPT-3 모델 기반에서만 fine-tune을 할 수 있습니다. fine-tuned 모델을 어떻게 사용할지에 대한 자세한 사항은 fine-tuning guide 를 참조하세요.
Do you store the data that is passed into the API?
OpenAI는 API로 전달된 데이터를 저장해서 갖고 있습니까?
As of March 1st, 2023, we retain your API data for 30 days but no longer use your data sent via the API to improve our models. Learn more in ourdata usage policy.
2023년 3월 1일 현재 OpenAI는 여러분의 API 데이터를 30일간 유지하고 있습니다. 하지만 여러분이 API를 통해 보낸 데이터들은 오리의 모델을 개선하는데 사용하지는 않습니다. 더 자세한 사항은 data usage policy 를 참조하세요.
Adding a moderation layer
조정 레이어 추가하기
If you want to add a moderation layer to the outputs of the Chat API, you can follow ourmoderation guideto prevent content that violates OpenAI’s usage policies from being shown.
Chat API의 output에 moderation 레이어를 추가할 수 있습니다. moderation 레이어를 추가하려는 경우 OpenAI의 사용 정책을 위반하는 내용이 표시되지 않도록 moderatin guide를 따라 주세요.