반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형

https://openai.com/blog/function-calling-and-other-api-updates

 

Function calling and other API updates

We’re announcing updates including more steerable API models, function calling capabilities, longer context, and lower prices.

openai.com

 

Function calling and other API updates

We’re announcing updates including more steerable API models, function calling capabilities, longer context, and lower prices.

우리는 더 조정 가능한 API 모델, 함수 호출 기능, 더 긴 컨텍스트 및 더 낮은 가격을 포함한 업데이트를 발표합니다.

 

June 13, 2023

AnnouncementsProduct

 

We released gpt-3.5-turbo and gpt-4 earlier this year, and in only a short few months, have seen incredible applications built by developers on top of these models.

 

우리는 올해 초에 gpt-3.5-turbo 및 gpt-4를 출시했고 불과 몇 달 만에 개발자들이 이러한 모델 위에 구축한 놀라운 애플리케이션을 보았습니다.

 

Today, we’re following up with some exciting updates:

 

오늘 우리는 다음과 같은 몇 가지 흥미로운 업데이트를 진행합니다.

 

  • new function calling capability in the Chat Completions API
  • Chat Completions API의 새로운 함수 호출 기능
  • updated and more steerable versions of gpt-4 and gpt-3.5-turbo
  • gpt-4 및 gpt-3.5-turbo의 업데이트되고 조정 가능한 버전
  • new 16k context version of gpt-3.5-turbo (vs the standard 4k version)
  • gpt-3.5-turbo의 새로운 16k 컨텍스트 버전(표준 4k 버전 대비)
  • 75% cost reduction on our state-of-the-art embeddings model
  • 최첨단 임베딩 모델로 비용 75% 절감
  • 25% cost reduction on input tokens for gpt-3.5-turbo
  • gpt-3.5-turbo의 입력 토큰 비용 25% 감소
  • announcing the deprecation timeline for the gpt-3.5-turbo-0301 and gpt-4-0314 models
  • gpt-3.5-turbo-0301 및 gpt-4-0314 모델에 대한 지원 중단 일정 발표

All of these models come with the same data privacy and security guarantees we introduced on March 1 — customers own all outputs generated from their requests and their API data will not be used for training.

 

이러한 모든 모델에는 3월 1일에 도입한 것과 동일한 데이터 개인 정보 보호 및 보안 보장이 제공됩니다. 고객은 요청에서 생성된 모든 출력을 소유하고 API 데이터는 교육에 사용되지 않습니다.

 

Function calling

Developers can now describe functions to gpt-4-0613 and gpt-3.5-turbo-0613, and have the model intelligently choose to output a JSON object containing arguments to call those functions. This is a new way to more reliably connect GPT's capabilities with external tools and APIs.

 

개발자는 이제 gpt-4-0613 및 gpt-3.5-turbo-0613에 함수를 설명하고 모델이 이러한 함수를 호출하기 위한 인수가 포함된 JSON 개체를 출력하도록 지능적으로 선택하도록 할 수 있습니다. 이는 GPT의 기능을 외부 도구 및 API와 보다 안정적으로 연결하는 새로운 방법입니다.

 

 

These models have been fine-tuned to both detect when a function needs to be called (depending on the user’s input) and to respond with JSON that adheres to the function signature. Function calling allows developers to more reliably get structured data back from the model. For example, developers can:

 

이러한 모델은 (사용자 입력에 따라) 함수를 호출해야 하는 시기를 감지하고 함수 서명을 준수하는 JSON으로 응답하도록 미세 조정되었습니다. 함수 호출을 통해 개발자는 모델에서 구조화된 데이터를 보다 안정적으로 가져올 수 있습니다. 예를 들어 개발자는 다음을 수행할 수 있습니다.

 

  • Create chatbots that answer questions by calling external tools (e.g., like ChatGPT Plugins)
  • 외부 도구(예: ChatGPT 플러그인)를 호출하여 질문에 답하는 챗봇 생성

 

Convert queries such as “Email Anya to see if she wants to get coffee next Friday” to a function call like send_email(to: string, body: string), or “What’s the weather like in Boston?” to get_current_weather(location: string, unit: 'celsius' | 'fahrenheit').

 

"다음 금요일에 커피를 마시고 싶은지 확인하기 위해 Anya에게 이메일 보내기"와 같은 쿼리를 send_email(to: 문자열, 본문: 문자열) 또는 "보스턴의 날씨는 어떻습니까?"와 같은 쿼리를 get_current_weather(location: string, unit: 'celsius' | 'fahrenheit') 함수 호출로 변환합니다.

 

  • Convert natural language into API calls or database queries
  • 자연어를 API 호출 또는 데이터베이스 쿼리로 변환

 

Convert “Who are my top ten customers this month?” to an internal API call such as get_customers_by_revenue(start_date: string, end_date: string, limit: int), or “How many orders did Acme, Inc. place last month?” to a SQL query using sql_query(query: string).

 

"이번 달 내 상위 10명의 고객은 누구입니까?" 를 get_customers_by_revenue(start_date: string, end_date: string, limit: int)과 같은 internal API 로 convert 합니다. 또는 "지난 달 Acme, Inc.에서 몇 건의 주문을 했습니까?"와 같은 내부 API 호출에 sql_query(query: string)를 사용한 SQL 쿼리로 변환합니다.

 

  • Extract structured data from text
  • 텍스트에서 구조화된 데이터 추출

 

Define a function called extract_people_data(people: [{name: string, birthday: string, location: string}]), to extract all people mentioned in a Wikipedia article.

 

extract_people_data(people: [{name: string, birthday: string, location: string}])라는 함수를 정의하여 Wikipedia 기사에 언급된 모든 사람을 추출합니다.

 

These use cases are enabled by new API parameters in our /v1/chat/completions endpoint, functions and function_call, that allow developers to describe functions to the model via JSON Schema, and optionally ask it to call a specific function. Get started with our developer documentation and add evals if you find cases where function calling could be improved

 

이러한 사용 사례는 개발자가 JSON 스키마를 통해 모델에 함수를 설명하고 선택적으로 특정 함수를 호출하도록 요청할 수 있는 /v1/chat/completions 엔드포인트, functions 및 function_call의 새로운 API 매개변수에 의해 활성화됩니다. 개발자 설명서를 시작하고 함수 호출을 개선할 수 있는 경우를 찾으면 평가를 추가하십시오.

 

Function calling example

Request

curl https://api.openai.com/v1/chat/completions -u :$OPENAI_API_KEY -H 'Content-Type: application/json' -d '{
  "model": "gpt-3.5-turbo-0613",
  "messages": [
    {"role": "user", "content": "What is the weather like in Boston?"}
  ],
  "functions": [
    {
      "name": "get_current_weather",
      "description": "Get the current weather in a given location",
      "parameters": {
        "type": "object",
        "properties": {
          "location": {
            "type": "string",
            "description": "The city and state, e.g. San Francisco, CA"
          },
          "unit": {
            "type": "string",
            "enum": ["celsius", "fahrenheit"]
          }
        },
        "required": ["location"]
      }
    }
  ]
}'

Response

 

{
  "id": "chatcmpl-123",
  ...
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": null,
      "function_call": {
        "name": "get_current_weather",
        "arguments": "{ \"location\": \"Boston, MA\"}"
      }
    },
    "finish_reason": "function_call"
  }]
}

 

 

Request

curl https://weatherapi.com/...

Response

{ "temperature": 22, "unit": "celsius", "description": "Sunny" }

 

 

Request

curl https://api.openai.com/v1/chat/completions -u :$OPENAI_API_KEY -H 'Content-Type: application/json' -d '{
  "model": "gpt-3.5-turbo-0613",
  "messages": [
    {"role": "user", "content": "What is the weather like in Boston?"},
    {"role": "assistant", "content": null, "function_call": {"name": "get_current_weather", "arguments": "{ \"location\": \"Boston, MA\"}"}},
    {"role": "function", "name": "get_current_weather", "content": "{\"temperature\": "22", \"unit\": \"celsius\", \"description\": \"Sunny\"}"}
  ],
  "functions": [
    {
      "name": "get_current_weather",
      "description": "Get the current weather in a given location",
      "parameters": {
        "type": "object",
        "properties": {
          "location": {
            "type": "string",
            "description": "The city and state, e.g. San Francisco, CA"
          },
          "unit": {
            "type": "string",
            "enum": ["celsius", "fahrenheit"]
          }
        },
        "required": ["location"]
      }
    }
  ]
}'

 

Response

{
  "id": "chatcmpl-123",
  ...
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": "The weather in Boston is currently sunny with a temperature of 22 degrees Celsius.",
    },
    "finish_reason": "stop"
  }]
}

 

Since the alpha release of ChatGPT plugins, we have learned much about making tools and language models work together safely. However, there are still open research questions. For example, a proof-of-concept exploit illustrates how untrusted data from a tool’s output can instruct the model to perform unintended actions. We are working to mitigate these and other risks. Developers can protect their applications by only consuming information from trusted tools and by including user confirmation steps before performing actions with real-world impact, such as sending an email, posting online, or making a purchase.

 

ChatGPT 플러그인의 알파 릴리스 이후로 우리는 도구와 언어 모델이 안전하게 함께 작동하도록 만드는 방법에 대해 많은 것을 배웠습니다. 그러나 여전히 열려 있는 연구 질문이 있습니다. 예를 들어 개념 증명 익스플로잇은 도구 출력의 신뢰할 수 없는 데이터가 의도하지 않은 작업을 수행하도록 모델에 지시할 수 있는 방법을 보여줍니다. 우리는 이러한 위험 및 기타 위험을 완화하기 위해 노력하고 있습니다. 개발자는 신뢰할 수 있는 도구의 정보만 사용하고 이메일 보내기, 온라인 게시 또는 구매와 같은 실제 영향이 있는 작업을 수행하기 전에 사용자 확인 단계를 포함하여 애플리케이션을 보호할 수 있습니다.

 

 

New models

 

GPT-4

 

gpt-4-0613 includes an updated and improved model with function calling.

 

gpt-4-0613에는 함수 호출로 업데이트되고 개선된 모델이 포함되어 있습니다.

 

gpt-4-32k-0613 includes the same improvements as gpt-4-0613, along with an extended context length for better comprehension of larger texts.

 

gpt-4-32k-0613에는 gpt-4-0613과 동일한 개선 사항이 포함되어 있으며 더 큰 텍스트를 더 잘 이해할 수 있도록 컨텍스트 길이가 확장되었습니다.

 

With these updates, we’ll be inviting many more people from the waitlist to try GPT-4 over the coming weeks, with the intent to remove the waitlist entirely with this model. Thank you to everyone who has been patiently waiting, we are excited to see what you build with GPT-4!

 

이 업데이트를 통해 우리는 이 모델로 대기자 명단을 완전히 제거하기 위해 앞으로 몇 주 동안 대기자 명단에서 더 많은 사람들을 초대하여 GPT-4를 시도할 것입니다. 끈기 있게 기다려주신 모든 분들께 감사드립니다. 여러분이 GPT-4로 빌드하는 것을 보게 되어 기쁩니다!

 

GPT-3.5 Turbo

 

gpt-3.5-turbo-0613 includes the same function calling as GPT-4 as well as more reliable steerability via the system message, two features that allow developers to guide the model's responses more effectively.

 

gpt-3.5-turbo-0613에는 GPT-4와 동일한 기능 호출과 시스템 메시지를 통한 보다 안정적인 조종성, 개발자가 모델의 응답을 보다 효과적으로 안내할 수 있는 두 가지 기능이 포함되어 있습니다.

 

gpt-3.5-turbo-16k offers 4 times the context length of gpt-3.5-turbo at twice the price: $0.003 per 1K input tokens and $0.004 per 1K output tokens. 16k context means the model can now support ~20 pages of text in a single request.

 

gpt-3.5-turbo-16k는 두 배의 가격으로 gpt-3.5-turbo 컨텍스트 길이의 4배를 제공합니다: 입력 토큰 1,000개당 $0.003 및 출력 토큰 1,000개당 $0.004. 16k 컨텍스트는 이제 모델이 단일 요청에서 최대 20페이지의 텍스트를 지원할 수 있음을 의미합니다.

 

 

Model deprecations

Today, we’ll begin the upgrade and deprecation process for the initial versions of gpt-4 and gpt-3.5-turbo that we announced in March. Applications using the stable model names (gpt-3.5-turbo, gpt-4, and gpt-4-32k) will automatically be upgraded to the new models listed above on June 27th. For comparing model performance between versions, our Evals library supports public and private evals to show how model changes will impact your use cases. 

 

오늘 우리는 3월에 발표한 gpt-4 및 gpt-3.5-turbo의 초기 버전에 대한 업그레이드 및 사용 중단 프로세스를 시작합니다. 안정적인 모델 이름(gpt-3.5-turbo, gpt-4 및 gpt-4-32k)을 사용하는 애플리케이션은 6월 27일에 위에 나열된 새 모델로 자동 업그레이드됩니다. 버전 간 모델 성능을 비교하기 위해 Evals 라이브러리는 공개 및 비공개 평가를 지원하여 모델 변경이 사용 사례에 어떤 영향을 미치는지 보여줍니다.

 

 

Developers who need more time to transition can continue using the older models by specifying gpt-3.5-turbo-0301, gpt-4-0314, or gpt-4-32k-0314 in the ‘model’ parameter of their API request. These older models will be accessible through September 13th, after which requests specifying those model names will fail. You can stay up to date on model deprecations via our model deprecation page. This is the first update to these models; so, we eagerly welcome developer feedback to help us ensure a smooth transition.

 

전환하는 데 시간이 더 필요한 개발자는 API 요청의 '모델' 매개변수에 gpt-3.5-turbo-0301, gpt-4-0314 또는 gpt-4-32k-0314를 지정하여 이전 모델을 계속 사용할 수 있습니다. 이러한 이전 모델은 9월 13일까지 액세스할 수 있으며 그 이후에는 해당 모델 이름을 지정하는 요청이 실패합니다. 모델 지원 중단 페이지를 통해 모델 지원 중단에 대한 최신 정보를 확인할 수 있습니다. 이것은 이러한 모델에 대한 첫 번째 업데이트입니다. 따라서 원활한 전환을 보장하는 데 도움이 되는 개발자 피드백을 기꺼이 환영합니다.

 

 

Lower pricing

We continue to make our systems more efficient and are passing those savings on to developers, effective today.

우리는 계속해서 시스템을 더 효율적으로 만들고 이러한 절감액을 개발자에게 전달하고 있습니다. 오늘부터 유효합니다.

 

Embeddings

text-embedding-ada-002 is our most popular embeddings model. Today we’re reducing the cost by 75% to $0.0001 per 1K tokens.

text-embedding-ada-002는 가장 인기 있는 임베딩 모델입니다. 오늘 우리는 비용을 75% 줄여 1,000개 토큰당 $0.0001입니다.

 

GPT-3.5 Turbo

gpt-3.5-turbo is our most popular chat model and powers ChatGPT for millions of users. Today we're reducing the cost of gpt-3.5-turbo’s input tokens by 25%. Developers can now use this model for just $0.0015 per 1K input tokens and $0.002 per 1K output tokens, which equates to roughly 700 pages per dollar.

gpt-3.5-turbo는 당사의 가장 인기 있는 채팅 모델이며 수백만 명의 사용자를 위한 ChatGPT를 지원합니다. 오늘 우리는 gpt-3.5-turbo의 입력 토큰 비용을 25%까지 줄입니다. 개발자는 이제 이 모델을 1K 입력 토큰당 $0.0015 및 1K 출력 토큰당 $0.002로 사용할 수 있습니다. 이는 달러당 약 700페이지에 해당합니다.

 

gpt-3.5-turbo-16k will be priced at $0.003 per 1K input tokens and $0.004 per 1K output tokens.

 

gpt-3.5-turbo-16k의 가격은 입력 토큰 1,000개당 $0.003, 출력 토큰 1,000개당 $0.004입니다.

 

Developer feedback is a cornerstone of our platform’s evolution and we will continue to make improvements based on the suggestions we hear. We’re excited to see how developers use these latest models and new features in their applications.

 

개발자 피드백은 우리 플랫폼 발전의 초석이며 우리는 우리가 듣는 제안을 기반으로 계속해서 개선할 것입니다. 개발자가 애플리케이션에서 이러한 최신 모델과 새로운 기능을 어떻게 사용하는지 보게 되어 기쁩니다.

 

 

반응형

Chat GPT Plugin - Plugins in production

2023. 4. 4. 21:58 | Posted by 솔웅


반응형

Production - OpenAI API

 

OpenAI API

An API for accessing new AI models developed by OpenAI

platform.openai.com

 

 

Rate limits

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 the ai-plugin.json manifest 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 the Plugin Terms.

 

플러그인을 등록하려면 Plugin Terms에 동의해야 합니다.

 

Domain verification and security

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 has www. as a subdomain, then the root domain will strip out www. 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가 없는 도메인으로 리디렉션하는 경우입니다.

 

Examples of what the root domain looks like:

 

루트 도메인의 예는 다음과 같습니다.

 

 

Manifest validation

Specific fields in the manifest itself must satisfy the following requirements:

 

매니페스트 자체의 특정 필드는 다음 요구 사항을 충족해야 합니다.

 

  • api.url - the URL provided to the OpenAPI spec must be hosted at the same level or a subdomain of the root domain.
  • api.url - OpenAPI 사양에 제공된 URL은 동일한 수준 또는 루트 도메인의 하위 도메인에서 호스팅되어야 합니다.
  • legal_info - The second-level domain of the URL provided must be the same as the second-level domain of the root domain.
  • legal_info - 제공된 URL의 2단계 도메인은 루트 도메인의 2단계 도메인과 동일해야 합니다.
  • 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

The api.url field in the manifest provides a link to an OpenAPI spec that defines APIs that the plugin can call into. OpenAPI allows specifying multiple server 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 on api.example.com, then api.example.com will 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 the ai-plugin.json file, 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 the CIDR block 23.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 plugin crawls websites from 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명의 사용자가 설치할 수 있습니다. 출시 시 액세스 권한이 있는 다른 개발자만 플러그인을 설치할 수 있습니다. 우리는 시간이 지남에 따라 액세스를 확장할 계획이며 궁극적으로 모든 사용자가 사용할 수 있게 되기 전에 검토를 위해 플러그인을 제출하는 프로세스를 출시할 것입니다.

 

 

반응형

Chat GPT Plugin - Example plugins

2023. 4. 4. 02:54 | Posted by 솔웅


반응형

Examples - OpenAI API

 

OpenAI API

An API for accessing new AI models developed by OpenAI

platform.openai.com

 

 

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 more powerful retrieval plugin, these examples provide a glimpse into what we hope to make possible with plugins.

 

building을 시작하기 위해 다양한 인증 스키마 및 사용 사례를 다루는 간단한 플러그인 세트를 제공하고 있습니다. 단순한 no authentication todo list  플러그인에서 더 강력한 검색 플러그인에 이르기까지 이 예제는 플러그인으로 가능하게 하고자 하는 것을 엿볼 수 있는 기회를 제공합니다.

 

During development, you can run the plugin locally on your computer or through a cloud development environment like GitHub Codespaces, Replit, or CodeSandbox.

 

개발 중에 플러그인을 컴퓨터에서 로컬로 실행하거나 GitHub Codespaces, Replit 또는 CodeSandbox와 같은 클라우드 개발 환경을 통해 실행할 수 있습니다.

 

 

Learn how to build a simple todo list plugin with no auth

 

To start, define an ai-plugin.json file 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 the PLUGIN_HOSTNAME should 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 an ai-plugin.json file 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 an ai-plugin.json file 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 the PLUGIN_HOSTNAME should 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

 

The ChatGPT retrieval plugin is 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 검색 플러그인은 더 완전한 기능을 갖춘 코드 예제입니다. 플러그인의 범위는 넓기 때문에 코드를 자세히 읽고 고급 플러그인이 어떻게 생겼는지 확인하는 것이 좋습니다.

 

The retrieval plugin includes:

검색 플러그인에는 다음이 포함됩니다.

  • Support for multiple vector databases providers
  • 여러 벡터 데이터베이스 공급자 지원
  • All 4 different authentication methods
  • 4가지 인증 방법 모두
  • Multiple different API features
  • 다양한 API 기능
반응형

Chat GPT Plugin - Authentication

2023. 4. 4. 00:17 | Posted by 솔웅


반응형

Authentication - OpenAI API

 

OpenAI API

An API for accessing new AI models developed by OpenAI

platform.openai.com

 

Plugin authentication

Plugins offer numerous authentication schemas to accommodate various use cases. To specify the authentication schema for your plugin, use the manifest file. Our plugin domain policy outlines our strategy for addressing domain security issues. For examples of available authentication options, refer to the examples 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]").
"auth": {
  "type": "service_http",
  "authorization_type": "bearer",
  "verification_tokens": {
    "openai": "cb7cdfb8a57e45bc8ad7dea5bc2f8324"
  }
},

 

User level

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]").
"auth": {
  "type": "user_http",
  "authorization_type": "bearer",
},

 

OAuth

The plugin protocol is compatible with OAuth. A simple example of the OAuth flow we are expecting in the manifest looks like the following:

 

플러그인 프로토콜은 OAuth와 호환됩니다. 매니페스트에서 예상되는 OAuth 흐름의 간단한 예는 다음과 같습니다.

 

  • To start, a developer pastes in their OAuth client id and client secret
  • 시작하려면 개발자가 OAuth 클라이언트 ID와 클라이언트 비밀번호를 붙여넣습니다. 
    • Then they have to add the verification token to their manifest file
    • 그런 다음 매니페스트 파일에 확인 토큰을 추가해야 합니다.
  • We store an encrypted version of the client secret
  • 클라이언트 시크릿의 암호화된 버전을 저장합니다.
  • Users log in through the plugin’s website when they install the plugin
  • 사용자는 플러그인을 설치할 때 플러그인 웹 사이트를 통해 로그인합니다. 
    • That gives us an OAuth access token (and optionally a refresh token) for the user, which we store encrypted
    • 그러면 사용자에 대한 OAuth 액세스 토큰(및 선택적으로 새로 고침 토큰)이 제공되며 암호화되어 저장됩니다.
  • Last, we pass that user’s token in the Authorization header when making requests to the plugin (“Authorization”: “[Bearer/Basic][user’s token]”)
  • 마지막으로 플러그인에 요청을 할 때 Authorization 헤더에 해당 사용자의 토큰을 전달합니다("Authorization": "[Bearer/Basic][user's token]").
"auth": {
  "type": "oauth",
  "client_url": "https://my_server.com/authorize",
  "scope": "",
  "authorization_url": "https://my_server.com/token",
  "authorization_content_type": "application/json",
  "verification_tokens": {
    "openai": "abc123456"
  }
},

 

 

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 OAuth client_id and client_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 to authorization_url with content type authorization_content_type and 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_type and 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] }
반응형

Chat GPT Plugin - Getting started

2023. 3. 27. 22:17 | Posted by 솔웅


반응형

Getting Started - OpenAI API

 

OpenAI API

An API for accessing new AI models developed by OpenAI

platform.openai.com

 

Creating a plugin takes three steps:

플러그인 생성에는 세 단계가 필요합니다.

  • Build an API
  • API 빌드
  • Document the API in the OpenAPI yaml or JSON format
  • OpenAPI yaml 또는 JSON 형식으로 API 문서화
  • Create a JSON manifest file that will define relevant metadata for the plugin
  • 플러그인에 대한 관련 메타데이터를 정의할 JSON 매니페스트 파일을 생성합니다.

The focus of the rest of this section will be creating a to-do list plugin by defining the OpenAPI specification along with the manifest file.

이 섹션의 나머지 부분에서는 매니페스트 파일과 함께 OpenAPI 사양을 정의하여 to-do list 플러그인을 만드는 데 초점을 맞춥니다.

 

 

Plugin manifest

Every plugin requires a ai-plugin.json file, 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 an https://example.com domain 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-known folder 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 required ai-plugin.json file 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', }
ManifestAuth ManifestAuth ManifestNoAuth, ManifestServiceHttpAuth, ManifestUserHttpAuth, ManifestOAuthAuth

 

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 for name_for_model
  • name_for_model은 최대 50자
  • 120 character max for description_for_human
  • description_for_human은 최대 120자
  • 8000 character max just for description_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자 제한(시간이 지남에 따라 줄어듦)도 변경될 수 있습니다.

 

OpenAPI definition

 

The next step is to build the OpenAPI specification to document the API.

다음 단계는 OpenAPI 사양을 빌드하여 API를 문서화하는 것입니다.

 

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에서 쿼리가 실행되면 정보 섹션에 정의된 설명을 보고 플러그인이 사용자 쿼리와 관련이 있는지 확인합니다.

 

You can read more about prompting in the writing descriptions section.

writing descriptions  섹션에서 프롬프트에 대한 자세한 내용을 읽을 수 있습니다.

 

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 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.

 

이 예제를 로컬에서 실행하고 있으므로 로컬 호스트 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 the description_for_model in 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 the description_for_model with “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 your description_for_model and descriptions in your OpenAPI specification, as well as when designing your API responses:

 

다음은 OpenAPI 사양에 description_for_model 및 설명을 작성할 때와 API 응답을 디자인할 때 따라야 할 몇 가지 모범 사례입니다.

 

  1. 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]
  2. 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.

    좋은 예
  3. The TODO list can add, remove and view the user's TODOs.
  4. 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."

    좋은 예
  5. [no instructions needed for this]
  6. 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!

  7. 좋은 예
    { "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 콘솔에 오류가 표시될 수 있습니다.

 

 

 

반응형

March 20 ChatGPT outage: Here’s what happened

2023. 3. 27. 21:44 | Posted by 솔웅


반응형

An update on our findings, the actions we’ve taken, and technical details of the bug.

우리가 발견한 사항, 우리가 취한 조치, 버그에 대한 기술적 세부 사항에 대한 업데이트입니다.

 

 

March 20 ChatGPT outage: Here’s what happened (openai.com)

 

March 20 ChatGPT outage: Here’s what happened

An update on our findings, the actions we’ve taken, and technical details of the bug.

openai.com

 

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 more technical details of 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 were active during a specific nine-hour window. In the hours before we took ChatGPT offline on Monday, it was possible for some users to see another active 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. 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, another active ChatGPT 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.

우리는 Redis 커뮤니티를 지속적으로 지원하고 기여하기 위해 최선을 다하고 있습니다.

반응형

OpenAI API - ChatGPT plugins

2023. 3. 25. 23:24 | Posted by 솔웅


반응형

https://openai.com/blog/chatgpt-plugins

 

ChatGPT plugins

We’ve implemented initial support for plugins in ChatGPT. Plugins are tools designed specifically for language models with safety as a core principle, and help ChatGPT access up-to-date information, run computations, or use third-party services.

openai.com

 

 

 

In line with our iterative deployment philosophy, we are gradually rolling out plugins in ChatGPT so we can study their real-world use, impact, and safety and alignment challenges—all of which we’ll have to get right in order to achieve our mission.

 

우리의 반복적인 배포(iterative deployment) 철학에 따라 우리는 ChatGPT에서 플러그인을 점진적으로 출시하여 실제 사용, 영향, 안전 및 alignment 문제를 연구할 수 있습니다. 이러한 일들을 통해서 우리의 미션을 달성하기 위한 옳은 방향으로 가게 될 것입니다.

 

Users have been asking for plugins since we launched ChatGPT (and many developers are experimenting with similar ideas) because they unlock a vast range of possible use cases. We’re starting with a small set of users and are planning to gradually roll out larger-scale access as we learn more (for plugin developers, ChatGPT users, and after an alpha period, API users who would like to integrate plugins into their products). We’re excited to build a community shaping the future of the human–AI interaction paradigm.

 

사용자는 ChatGPT를 출시한 이후로 플러그인을 요청받아 왔으며 많은 개발자가 유사한 아이디어를 실험하고 있습니다. 가능한 사용 사례가 광범위하기 때문입니다. 우리는 소수의 사용자로 시작하여 더 많은 것을 알게 됨에 따라 점진적으로 더 큰 규모의 액세스를 출시할 계획입니다(플러그인 개발자, ChatGPT 사용자 및 알파 기간 이후 플러그인을 제품에 통합하려는 API 사용자). 우리는 앞으로 human-AI 상호 작용 패러다임의 미래를 만들어 나갈 커뮤니티를 건설해 나가는데 대해 아주 exciting합니다.

 

Plugin developers who have been invited off our waitlist can use our documentation to build a plugin for ChatGPT, which then lists the enabled plugins in the prompt shown to the language model as well as documentation to instruct the model how to use each. The first plugins have been created by Expedia, FiscalNote, Instacart, KAYAK, Klarna, Milo, OpenTable, Shopify, Slack, Speak, Wolfram, and Zapier.

 

대기자 명단에서 선택 돼 나온 플러그인 개발자는 문서를 사용하여 ChatGPT용 플러그인을 빌드할 수 있습니다. 그런 다음 언어 모델에 표시되는 프롬프트에 활성화된 플러그인을 나열하고 모델에 각 사용 방법을 지시하는 문서를 나열합니다. 첫 번째 플러그인은 Expedia, FiscalNote, Instacart, KAYAK, Klarna, Milo, OpenTable, Shopify, Slack, Speak, Wolfram 및 Zapier에서 만들었습니다.

 

 

반응형


반응형

https://platform.openai.com/docs/plugins/introduction

 

OpenAI API

An API for accessing new AI models developed by OpenAI

platform.openai.com

 

Chat Plugins 

Limited Alpha

Learn how to build a plugin that allows ChatGPT to intelligently call your API.

 

ChatGPT가 API를 지능적으로 call 할 수 있도록 하는 플러그인을 빌드하는 방법을 알아보세요.

 

Introduction

OpenAI plugins connect ChatGPT to third-party applications. These plugins enable ChatGPT to interact with APIs defined by developers, enhancing ChatGPT's capabilities and allowing it to perform a wide range of actions.

 

OpenAI 플러그인은 ChatGPT를 타사 애플리케이션에 연결합니다. 이러한 플러그인을 통해 ChatGPT는 개발자가 정의한 API와 상호 작용하여 ChatGPT의 기능을 향상하고 광범위한 작업을 수행할 수 있습니다.

 

  • Plugins can allow ChatGPT to do things like:
  • 플러그인을 통해 ChatGPT는 다음과 같은 작업을 수행할 수 있습니다.
  • Retrieve real-time information; e.g., sports scores, stock prices, the latest news, etc.
  • 실시간 정보 검색 예: 스포츠 점수, 주가, 최신 뉴스 등
  • Retrieve knowledge-base information; e.g., company docs, personal notes, etc.
  • 지식 기반 정보를 검색합니다. 예: 회사 문서, 개인 메모 등
  • Perform actions on behalf of the user; e.g., booking a flight, ordering food, etc.
  • 사용자를 대신하여 작업을 수행합니다. 예: 비행기 예약, 음식 주문 등

 

Plugins are in a limited alpha and may not yet be accessible to you. Please join the waitlist to get access. During the alpha, we will be working closely with users and developers to iterate on the plugin system, which may evolve significantly.

 

플러그인은 제한된 알파 상태이며 아직 액세스할 수 없을겁니다. 액세스하려면 대기자 명단에 등록하십시오. 알파 기간 동안 우리는 사용자 및 개발자와 긴밀히 협력하여 크게 발전할 수 있는 플러그인 시스템을 반복할 것입니다.

 

Plugin developers expose one or more API endpoints, accompanied by a standardized manifest file and an OpenAPI specification. These define the plugin's functionality, allowing ChatGPT to consume the files and make calls to the developer-defined APIs.

 

플러그인 개발자는 표준화된 매니페스트 파일 및 OpenAPI 사양과 함께 하나 이상의 API 엔드포인트를 노출합니다. 이들은 플러그인의 기능을 정의하여 ChatGPT가 파일을 사용하고 개발자 정의 API를 호출할 수 있도록 합니다.

 

The AI model acts as an intelligent API caller. Given an API spec and a natural-language description of when to use the API, the model proactively calls the API to perform actions. For instance, if a user asks, "Where should I stay in Paris for a couple nights?", the model may choose to call a hotel reservation plugin API, receive the API response, and generate a user-facing answer combining the API data and its natural language capabilities.

 

AI 모델은 지능형 API 호출자 역할을 합니다. API 사양과 API 사용 시기에 대한 자연어 설명이 주어지면 모델은 사전에 API를 호출하여 작업을 수행합니다. 예를 들어 사용자가 "파리에서 며칠 밤을 묵어야 합니까?"라고 묻는 경우 모델은 호텔 예약 플러그인 API를 호출하고 API 응답을 수신하고 API 데이터를 결합한 사용자 대면 답변을 생성하도록 선택할 수 있습니다. 그리고 ChatGPT의 자연 언어 기능으로 이를 처리 할 것입니다.

 

Over time, we anticipate the system will evolve to accommodate more advanced use cases.

 

시간이 지남에 따라 시스템이 고급 사용 사례를 수용하도록 발전할 것으로 예상합니다.

 

Plugin flow

To build a plugin, it is important to understand the end-to-end flow.

 

플러그인을 구축하려면 end-to-end 흐름을 이해하는 것이 중요합니다.

 

  1. Create a manifest file and host it at yourdomain.com/.well-known/ai-plugin.json
    매니페스트 파일을 만들고 yourdomain.com/.well-known/ai-plugin.json에서 호스트합니다. 
    • The file includes metadata about your plugin (name, logo, etc.), details about authentication required (type of auth, OAuth URLs, etc.), and an OpenAPI spec for the endpoints you want to expose.
    • 이 파일에는 플러그인에 대한 메타데이터(이름, 로고 등), 필요한 인증에 대한 세부 정보(인증 유형, OAuth URL 등), 노출하려는 엔드포인트에 대한 OpenAPI 사양이 포함됩니다.
    • The model will see the OpenAPI description fields, which can be used to provide a natural language description for the different fields.
    • 모델은 다양한 필드에 대한 자연어 설명을 제공하는 데 사용할 수 있는 OpenAPI 설명 필드를 볼 수 있습니다.
    • We suggest exposing only 1-2 endpoints in the beginning with a minimum number of parameters to minimize the length of the text. The plugin description, API requests, and API responses are all inserted into the conversation with ChatGPT. This counts against the context limit of the model.
    • 텍스트 길이를 최소화하기 위해 최소한의 매개변수로 처음에 1-2개의 endpoint만 노출하는 것이 좋습니다. 플러그인 설명, API 요청 및 API 응답은 모두 ChatGPT와의 대화에 삽입됩니다. 이는 모델의 컨텍스트 제한에 포함됩니다.

 

  1. Register your plugin in the ChatGPT UI
    • Select the plugin model from the top drop down, then select “Plugins”, “Plugin Store”, and finally “Install an unverified plugin” or “Develop your own plugin”.
    • 상단 드롭다운에서 플러그인 모델을 선택한 다음 "플러그인", "플러그인 스토어"를 선택하고 마지막으로 "확인되지 않은 플러그인 설치" 또는 "자체 플러그인 개발"을 선택합니다.
    • If authentication is required, provide an OAuth 2 client_id and client_secret or an API key 
    • 인증이 필요한 경우 OAuth 2 client_id 및 client_secret 또는 API 키를 제공하십시오.

 

  1. Users activate your plugin
    사용자가 플러그인을 활성화합니다. 
    • Users must manually activate your plugin in the ChatGPT UI. (ChatGPT will not use your plugin by default.)
    • 사용자는 ChatGPT UI에서 플러그인을 수동으로 활성화해야 합니다. (ChatGPT는 기본적으로 플러그인을 사용하지 않습니다.)
    • During the alpha, plugin developers will be able to share their plugin with 15 additional users (only other developers can install unverified plugins currently). Overtime we will roll out a way to submit your plugin for review to be exposed to all of ChatGPT’s user base.
    • 알파 기간 동안 플러그인 개발자는 15명의 추가 사용자와 플러그인을 공유할 수 있습니다(현재 다른 개발자만 확인되지 않은 플러그인을 설치할 수 있음). 시간이 지나면 모든 ChatGPT 사용자 기반에 노출될 검토를 위해 플러그인을 제출하는 방법을 출시할 것입니다.
    • If auth is required, users will be redirected via OAuth to your plugin; you can optionally create new accounts here as well.
    • 인증이 필요한 경우 사용자는 OAuth를 통해 플러그인으로 리디렉션됩니다. 선택적으로 여기에서 새 계정을 만들 수도 있습니다.
    • In the future, we hope to build features to help users discover useful & popular plugins.
    • 앞으로는 사용자가 유용하고 인기 있는 플러그인을 찾는 데 도움이 되는 기능을 구축할 수 있기를 바랍니다.

 

  1. Users begin a conversation
    • OpenAI will inject a compact description of your plugin in a message to ChatGPT, invisible to end users. This will include the plugin description, endpoints, and examples.
    • OpenAI는 최종 사용자에게 보이지 않는 ChatGPT 메시지에 플러그인에 대한 간략한 설명을 삽입합니다. 여기에는 플러그인 설명, 끝점 및 예제가 포함됩니다.
    • When a user asks a relevant question, the model may choose to invoke an API call from your plugin if it seems relevant; for POST requests, we require that developers build a user confirmation flow.
    • 사용자가 관련 질문을 할 때 모델은 관련이 있다고 판단되면 플러그인에서 API call을 호출하도록 선택할 수 있습니다. POST 요청의 경우 개발자가 사용자 확인 흐름을 구축해야 합니다.
    • The model will incorporate the API results into its response to the user.
    • 모델은 API 결과를 사용자에 대한 응답에 통합합니다.
    • The model might include links returned from API calls in its response. These will be displayed as rich previews (using the OpenGraph protocol, where we pull the site_name, title, description, image, and url fields)"
    • 모델은 응답에 API 호출에서 반환된 링크를 포함할 수 있습니다. 풍부한 미리보기로 표시됩니다(Site_name, 제목, 설명, 이미지 및 URL 필드를 가져오는 OpenGraph 프로토콜 사용)"

 

Currently, we will be sending the user’s country and state in the Plugin conversation header (if you are in California for example, it would look like {"openai-subdivision-1-iso-code": "US-CA"}. For further data sources, users will have to opt in via a consent screen. This is useful for shopping, restaurants, weather, and more. You can read more in our developer terms of use.

 

현재 플러그인 대화 헤더에 사용자의 국가와 주를 보낼 예정입니다(예를 들어 캘리포니아에 있는 경우 {"openai-subdivision-1-iso-code": "US-CA"}와 같이 표시됨). 추가 데이터 소스를 사용하려면 사용자가 동의 화면을 통해 선택해야 합니다. 이것은 쇼핑, 레스토랑, 날씨 등에 유용합니다. 개발자 사용 약관에서 자세한 내용을 읽을 수 있습니다.

 

반응형

'Open AI > CHAT PLUGINS' 카테고리의 다른 글

Chat GPT Plugin - Plugin policies  (0) 2023.04.04
Chat GPT Plugin - Plugins in production  (0) 2023.04.04
Chat GPT Plugin - Example plugins  (0) 2023.04.04
Chat GPT Plugin - Authentication  (0) 2023.04.04
Chat GPT Plugin - Getting started  (0) 2023.03.27


반응형

Azure OpenAI를 사용하려면 해당 서비스를 사용할 수 있는 권한을 Microsoft 사로부터 얻어야 합니다.

저는 공부 목적으로 필요하다고 신청했는데 거부 됐습니다.

 

 

실제 이 Azure OpenAI를 이용해서 제품을 개발하고자 한다면 한번 신청해 보세요.

신청 방법은 아래 글에 정리 해 놨습니다.

https://coronasdk.tistory.com/1304

 

Azure OpenAI 를 사용하기 위한 사전 요구 사항들 - 사용 요청 거부 됨

OpenAI CookBook 을 거의 다 공부하고 Azure OpenAI 를 공부할 차례 입니다. https://github.com/openai/openai-cookbook GitHub - openai/openai-cookbook: Examples and guides for using the OpenAI API Examples and guides for using the OpenAI API. C

coronasdk.tistory.com

 

저는 일단 실습은 못하고 Cookbook에 있는 글로 공부해 보겠습니다.

 

https://github.com/openai/openai-cookbook/blob/main/examples/azure/finetuning.ipynb

 

GitHub - openai/openai-cookbook: Examples and guides for using the OpenAI API

Examples and guides for using the OpenAI API. Contribute to openai/openai-cookbook development by creating an account on GitHub.

github.com

 

Azure Fine tuning example

In this example we'll try to go over all operations that can be done using the Azure endpoints and their differences with the openAI endpoints (if any).

 

이 예제에서는 Azure endpoints 를  사용하여 수행할 수 있는 모든 작업과 openAI endpoints  (있는 경우)과의 차이점을 살펴보겠습니다.


This example focuses on finetuning but also touches on the majority of operations that are available using the API. This example is meant to be a quick way of showing simple operations and is not meant as a finetune model adaptation tutorial.

 

이 예제는 finetuning에 중점을 두지만 API를 사용하여 사용할 수 있는 대부분의 작업도 다룹니다. 이 예제는 간단한 작업을 빠르게 보여주기 위한 것이며 finetuning 모델 적용 튜토리얼이 아닙니다.

 

import openai
from openai import cli

 

Setup

For the following sections to work properly we first have to setup some things. Let's start with the api_base and api_version. To find your api_base go to https://portal.azure.com, find your resource and then under "Resource Management" -> "Keys and Endpoints" look for the "Endpoint" value.

 

다음 섹션이 제대로 작동하려면 먼저 몇 가지를 설정해야 합니다. api_base 및 api_version부터 시작하겠습니다. api_base를 찾으려면 https://portal.azure.com으로 이동하여 리소스를 찾은 다음 "Resource Management" -> "Keys and Endpoints"에서 "Endpoint" 값을 찾습니다.

 

openai.api_version = '2022-12-01'
openai.api_base = '' # Please add your endpoint here

 

We next have to setup the api_type and api_key. We can either get the key from the portal or we can get it through Microsoft Active Directory Authentication. Depending on this the api_type is either azure or azure_ad.

 

다음으로 api_type 및 api_key를 설정해야 합니다. 포털에서 키를 얻거나 Microsoft Active Directory 인증을 통해 얻을 수 있습니다. 이에 따라 api_type은 azure 또는 azure_ad입니다.

 

Setup: Portal

Let's first look at getting the key from the portal. Go to https://portal.azure.com, find your resource and then under "Resource Management" -> "Keys and Endpoints" look for one of the "Keys" values.

 

먼저 포털에서 키를 가져오는 방법을 살펴보겠습니다. https://portal.azure.com으로 이동하여 리소스를 찾은 다음 "Resource Management" -> "Keys and Endpoints"에서 "Keys" 값 중 하나를 찾습니다.

 

openai.api_type = 'azure'
openai.api_key = ''  # Please add your api key here

(Optional) Setup: Microsoft Active Directory Authentication

Let's now see how we can get a key via Microsoft Active Directory Authentication. Uncomment the following code if you want to use Active Directory Authentication instead of keys from the portal.

 

(선택 사항) 설정: Microsoft Active Directory 인증
이제 Microsoft Active Directory 인증을 통해 키를 얻는 방법을 살펴보겠습니다. 포털의 키 대신 Active Directory 인증을 사용하려면 다음 코드의 주석을 제거하십시오.

 

# from azure.identity import DefaultAzureCredential

# default_credential = DefaultAzureCredential()
# token = default_credential.get_token("https://cognitiveservices.azure.com/.default")

# openai.api_type = 'azure_ad'
# openai.api_key = token.token

 

Files

In the next section we will focus on the files operations: importing, listing, retrieving, deleting. For this we need to create 2 temporary files with some sample data. For the sake of simplicity, we will use the same data for training and validation.

 

다음 섹션에서는 가져오기, 나열, 검색, 삭제와 같은 파일 작업에 중점을 둘 것입니다. 이를 위해 일부 샘플 데이터로 2개의 임시 파일을 생성해야 합니다. 단순화를 위해 교육 및 검증에 동일한 데이터를 사용합니다.

 

import shutil
import json

training_file_name = 'training.jsonl'
validation_file_name = 'validation.jsonl'

sample_data = [{"prompt": "When I go to the store, I want an", "completion": "apple."},
    {"prompt": "When I go to work, I want a", "completion": "coffee."},
    {"prompt": "When I go home, I want a", "completion": "soda."}]

print(f'Generating the training file: {training_file_name}')
with open(training_file_name, 'w') as training_file:
    for entry in sample_data:
        json.dump(entry, training_file)
        training_file.write('\n')

print(f'Copying the training file to the validation file')
shutil.copy(training_file_name, validation_file_name)

 

Files: Listing

List all of the uploaded files and check for the ones that are named "training.jsonl" or "validation.jsonl"

 

업로드된 모든 파일을 나열하고 이름이 "training.jsonl" 또는 "validation.jsonl"인 파일을 확인합니다.

 

print('Checking for existing uploaded files.')
results = []
files = openai.File.list().data
print(f'Found {len(files)} total uploaded files in the subscription.')
for item in files:
    if item["filename"] in [training_file_name, validation_file_name]:
        results.append(item["id"])
print(f'Found {len(results)} already uploaded files that match our names.')

 

Files: Deleting

Let's now delete those found files (if any) since we're going to be re-uploading them next.

 

다음에 다시 업로드할 예정이므로 찾은 파일(있는 경우)을 삭제하겠습니다.

 

print(f'Deleting already uploaded files...')
for id in results:
    openai.File.delete(sid = id)

 

Files: Importing & Retrieving

Now, let's import our two files ('training.jsonl' and 'validation.jsonl') and keep those IDs since we're going to use them later for finetuning.

 

이제 두 파일('training.jsonl' 및 'validation.jsonl')을 가져오고 나중에 미세 조정에 사용할 것이므로 해당 ID를 유지하겠습니다.


For this operation we are going to use the cli wrapper which does a bit more checks before uploading and also gives us progress. In addition, after uploading we're going to check the status our import until it has succeeded (or failed if something goes wrong)

 

이 작업을 위해 업로드하기 전에 조금 더 확인하고 진행률을 제공하는 cli 래퍼를 사용할 것입니다. 또한 업로드 후 가져오기가 성공할 때까지(또는 무언가 잘못되면 실패할 때까지) 가져오기 상태를 확인합니다.

 

import time

def check_status(training_id, validation_id):
    train_status = openai.File.retrieve(training_id)["status"]
    valid_status = openai.File.retrieve(validation_id)["status"]
    print(f'Status (training_file | validation_file): {train_status} | {valid_status}')
    return (train_status, valid_status)

#importing our two files
training_id = cli.FineTune._get_or_upload(training_file_name, True)
validation_id = cli.FineTune._get_or_upload(validation_file_name, True)

#checking the status of the imports
(train_status, valid_status) = check_status(training_id, validation_id)

while train_status not in ["succeeded", "failed"] or valid_status not in ["succeeded", "failed"]:
    time.sleep(1)
    (train_status, valid_status) = check_status(training_id, validation_id)

 

Files: Downloading

Now let's download one of the files, the training file for example, to check that everything was in order during importing and all bits are there.

 

이제 파일 중 하나(예: 교육 파일)를 다운로드하여 가져오는 동안 모든 것이 제대로 작동하고 모든 비트가 있는지 확인합니다.

 

print(f'Downloading training file: {training_id}')
result = openai.File.download(training_id)
print(result.decode('utf-8'))

 

Finetune

In this section we are going to use the two training and validation files that we imported in the previous section, to train a finetune model.

 

이 섹션에서는 finetune  모델을 교육하기 위해 이전 섹션에서 가져온 두 개의 교육 및 검증 파일을 사용할 것입니다.

 

 

Finetune: Adapt

First let's create the finetune adaptation job.

먼저 미세 조정 적응 작업을 생성해 보겠습니다.

 

create_args = {
    "training_file": training_id,
    "validation_file": validation_id,
    "model": "babbage",
    "compute_classification_metrics": True,
    "classification_n_classes": 3,
    "n_epochs": 20,
    "batch_size": 3,
    "learning_rate_multiplier": 0.3
}
resp = openai.FineTune.create(**create_args)
job_id = resp["id"]
status = resp["status"]

print(f'Fine-tunning model with jobID: {job_id}.')

 

Finetune: Streaming

While the job runs, we can subscribe to the streaming events to check the progress of the operation.

작업이 실행되는 동안 스트리밍 이벤트를 구독하여 작업 진행 상황을 확인할 수 있습니다.

 

 

import signal
import datetime

def signal_handler(sig, frame):
    status = openai.FineTune.retrieve(job_id).status
    print(f"Stream interrupted. Job is still {status}.")
    return

print(f'Streaming events for the fine-tuning job: {job_id}')
signal.signal(signal.SIGINT, signal_handler)

events = openai.FineTune.stream_events(job_id)
try:
    for event in events:
        print(f'{datetime.datetime.fromtimestamp(event["created_at"])} {event["message"]}')

except Exception:
    print("Stream interrupted (client disconnected).")

 

Finetune: Listing and Retrieving

Now let's check that our operation was successful and in addition we can look at all of the finetuning operations using a list operation.

이제 작업이 성공했는지 확인하고 목록 작업을 사용하여 모든 finetune  작업을 볼 수 있습니다.

 

status = openai.FineTune.retrieve(id=job_id)["status"]
if status not in ["succeeded", "failed"]:
    print(f'Job not in terminal status: {status}. Waiting.')
    while status not in ["succeeded", "failed"]:
        time.sleep(2)
        status = openai.FineTune.retrieve(id=job_id)["status"]
        print(f'Status: {status}')
else:
    print(f'Finetune job {job_id} finished with status: {status}')

print('Checking other finetune jobs in the subscription.')
result = openai.FineTune.list()
print(f'Found {len(result.data)} finetune jobs.')

 

Finetune: Deleting

Finally we can delete our finetune job.
WARNING: Please skip this step if you want to continue with the next section as the finetune model is needed. (The delete code is commented out by default)

 

마지막으로 finetune  작업을 삭제할 수 있습니다.
경고: finetune 모델이 필요하므로 다음 섹션을 계속하려면 이 단계를 건너뛰십시오. (삭제 코드는 기본적으로 주석 처리됨)

 

# openai.FineTune.delete(sid=job_id)

 

Deployments

In this section we are going to create a deployment using the finetune model that we just adapted and then used the deployment to create a simple completion operation.

 

이 섹션에서는 방금 수정한 finetune  모델을 사용하여 deployment 를 생성한 다음 deployment 를 사용하여 간단한 completion  작업을 생성할 것입니다.

 

Deployments: Create

Let's create a deployment using the fine-tune model.

fine-tune모델을 사용하여 deployment 를 생성해 보겠습니다.

 

#Fist let's get the model of the previous job:
result = openai.FineTune.retrieve(id=job_id)
if result["status"] == 'succeeded':
    model = result["fine_tuned_model"]

# Now let's create the deployment
print(f'Creating a new deployment with model: {model}')
result = openai.Deployment.create(model=model, scale_settings={"scale_type":"standard"})
deployment_id = result["id"]

 

Deployments: Retrieving

Now let's check the status of the newly created deployment

이제 새로 생성된 배포의 상태를 확인하겠습니다.

 

print(f'Checking for deployment status.')
resp = openai.Deployment.retrieve(id=deployment_id)
status = resp["status"]
print(f'Deployment {deployment_id} is with status: {status}')

Deployments: Listing

Now because creating a new deployment takes a long time, let's look in the subscription for an already finished deployment that succeeded.

이제 새 deployment를 만드는 데 시간이 오래 걸리므로 이미 완료된 deployment에 대한 subscription 을 살펴보겠습니다.

 

print('While deployment running, selecting a completed one.')
deployment_id = None
result = openai.Deployment.list()
for deployment in result.data:
    if deployment["status"] == "succeeded":
        deployment_id = deployment["id"]
        break

if not deployment_id:
    print('No deployment with status: succeeded found.')
else:
    print(f'Found a successful deployment with id: {deployment_id}.')

 

Completions

Now let's send a sample completion to the deployment.

이제 deployment에 샘플 completion 을 보내겠습니다.

 

print('Sending a test completion job')
start_phrase = 'When I go home, I want a'
response = openai.Completion.create(deployment_id=deployment_id, prompt=start_phrase, temperature=0, stop=".")
text = response['choices'][0]['text'].replace('\n', '').replace(' .', '.').strip()
print(f'"{start_phrase} {text}."')

 

Deployments: Delete

Finally let's delete the deployment

마지막으로 deployment를 삭제하겠습니다.

 

print(f'Deleting deployment: {deployment_id}')
openai.Deployment.delete(sid=deployment_id)

 

반응형


반응형

Azure OpenAI를 사용하려면 해당 서비스를 사용할 수 있는 권한을 Microsoft 사로부터 얻어야 합니다.

저는 공부 목적으로 필요하다고 신청했는데 거부 됐습니다.

 

 

실제 이 Azure OpenAI를 이용해서 제품을 개발하고자 한다면 한번 신청해 보세요.

 

신청 방법은 아래 글에 정리 해 놨습니다.

 

https://coronasdk.tistory.com/1304

 

Azure OpenAI 를 사용하기 위한 사전 요구 사항들 - 사용 요청 거부 됨

OpenAI CookBook 을 거의 다 공부하고 Azure OpenAI 를 공부할 차례 입니다. https://github.com/openai/openai-cookbook GitHub - openai/openai-cookbook: Examples and guides for using the OpenAI API Examples and guides for using the OpenAI API. C

coronasdk.tistory.com

 

저는 일단 실습은 못하고 Cookbook에 있는 글로 공부해 보겠습니다.

 

https://github.com/openai/openai-cookbook/blob/main/examples/azure/embeddings.ipynb

 

GitHub - openai/openai-cookbook: Examples and guides for using the OpenAI API

Examples and guides for using the OpenAI API. Contribute to openai/openai-cookbook development by creating an account on GitHub.

github.com

 

 

참고로 Azure OpenAI Embeddings + Search 관련 유투브 클립입니다.

 

https://www.youtube.com/watch?v=ocxq84ocYi0 

 

아래부터 Cookbook 내용입니다.

 

Azure embeddings example

 

In this example we'll try to go over all operations for embeddings that can be done using the Azure endpoints.
This example focuses on embeddings but also touches some other operations that are also available using the API. This example is meant to be a quick way of showing simple operations and is not meant as a tutorial.

 

이 예제에서는 Azure endpoints를 사용하여 수행할 수 있는 embeddings 에 대한 작업을 살펴보겠습니다.
이 예제는 임베딩에 중점을 두지만 API를 사용하여 사용할 수 있는 다른 작업도 다룹니다. 이 예제는 간단한 작업을 보여주는 빠른 방법이며 튜토리얼이 아닙니다.

 

import openai
from openai import cli

Setup

For the following sections to work properly we first have to setup some things. Let's start with the api_base and api_version. To find your api_base go to https://portal.azure.com, find your resource and then under "Resource Management" -> "Keys and Endpoints" look for the "Endpoint" value.

 

다음 섹션이 제대로 작동하려면 먼저 몇 가지를 설정해야 합니다. api_base 및 api_version부터 시작하겠습니다. api_base를 찾으려면 https://portal.azure.com으로 이동하여 리소스를 찾은 다음 "Resource Management" -> "Keys and Endpoints" 에서 "Endpoint" 값을 찾습니다.

 

openai.api_version = '2022-12-01'
openai.api_base = '' # Please add your endpoint here

다음으로 api_type 및 api_key를 설정해야 합니다. 포털에서 키를 얻거나 Microsoft Active Directory 인증을 통해 얻을 수 있습니다. 이에 따라 api_type은 azure 또는 azure_ad입니다.

 

Setup: Portal

Let's first look at getting the key from the portal. Go to https://portal.azure.com, find your resource and then under "Resource Management" -> "Keys and Endpoints" look for one of the "Keys" values.

 

먼저 포털에서 키를 가져오는 방법을 살펴보겠습니다. https://portal.azure.com으로 이동하여 리소스를 찾은 다음 "Resource Management" -> "Keys and Endpoints"에서 "Keys" 값 중 하나를 찾습니다.

 

openai.api_type = 'azure'
openai.api_key = ''  # Please add your api key here

(Optional) Setup: Microsoft Active Directory Authentication

Let's now see how we can get a key via Microsoft Active Directory Authentication. Uncomment the following code if you want to use Active Directory Authentication instead of keys from the portal.

 

(선택 사항) 설정: Microsoft Active Directory 인증
이제 Microsoft Active Directory 인증을 통해 키를 얻는 방법을 살펴보겠습니다. 포털의 키 대신 Active Directory 인증을 사용하려면 다음 코드의 주석을 제거하십시오.

 

# from azure.identity import DefaultAzureCredential

# default_credential = DefaultAzureCredential()
# token = default_credential.get_token("https://cognitiveservices.azure.com/.default")

# openai.api_type = 'azure_ad'
# openai.api_key = token.token

 

Deployments

In this section we are going to create a deployment that we can use to create embeddings.

이 섹션에서는 embeddings을 만드는 데 사용할 수 있는 deployment 를 만들 것입니다.

 

Deployments: Create manually

Let's create a deployment using the text-similarity-curie-001 model. Create a new deployment by going to your Resource in your portal under "Resource Management" -> "Model deployments".

text-similarity-curie-001 모델을 사용하여 배포를 생성해 보겠습니다. "Resource Management" -> "Model deployments"에서 포털의 리소스로 이동하여 새 deployment를 만듭니다.

 

(Optional) Deployments: Create programatically

We can also create a deployment using code:

코드를 사용하여 deployment 를 만들 수도 있습니다.

 

model = "text-similarity-curie-001"

# Now let's create the deployment
print(f'Creating a new deployment with model: {model}')
result = openai.Deployment.create(model=model, scale_settings={"scale_type":"standard"})
deployment_id = result["id"]

 

(Optional) Deployments: Retrieving

Now let's check the status of the newly created deployment

이제 새로 생성된 배포의 상태를 확인하겠습니다.

print(f'Checking for deployment status.')
resp = openai.Deployment.retrieve(id=deployment_id)
status = resp["status"]
print(f'Deployment {deployment_id} is with status: {status}')

 

Deployments: Listing

Now because creating a new deployment takes a long time, let's look in the subscription for an already finished deployment that succeeded.

이제 새 deployment 를 만드는 데 시간이 오래 걸리므로 이미 완료된 deployment 에 대한 subscription 을 살펴보겠습니다.

 

print('While deployment running, selecting a completed one that supports embeddings.')
deployment_id = None
result = openai.Deployment.list()
for deployment in result.data:
    if deployment["status"] != "succeeded":
        continue
    
    model = openai.Model.retrieve(deployment["model"])
    if model["capabilities"]["embeddings"] != True:
        continue
    
    deployment_id = deployment["id"]
    break

if not deployment_id:
    print('No deployment with status: succeeded found.')
else:
    print(f'Found a succeeded deployment that supports embeddings with id: {deployment_id}.')

 

Embeddings

Now let's send a sample embedding to the deployment.

이제 배포에 샘플 임베딩을 보내겠습니다.

 

embeddings = openai.Embedding.create(deployment_id=deployment_id,
                                     input="The food was delicious and the waiter...")
                                
print(embeddings)

 

(Optional) Deployments: Delete

Finally let's delete the deployment

 

마지막으로 deployment를 삭제하겠습니다.

 

 

 

 

반응형
이전 1 2 3 4 5 다음