Концепция "custom GPT" в терминах OpenAI - это кастомный набор инструкций (custom prompt), который может быть создан любым пользователем ChatGPT с подпиской Plus. Каждый такой custom GPT за счет своего набора инструкций хорошо заточен под решение своей конкретной задачи. Есть custom GPT, которые хорошо пишут код, есть custom GPT, которые играют роль репетитора или психотерапевта и т.д.
Таким образом, GPT store - это большая библиотека инструкций для разных задач внутри ChatGPT. Она создается и поддерживается коммьюнити и очень сильно напоминает google play market или apple app store.
Процесс создания Custom GPT заключается в том, что в интерфейсе ChatGPT пользователь составляет подробные инструкции, что и как его GPT должен делать, дает описание, придумывает название, примеры использования и т.д. - всё это сохраняется на серверах OpenAI.
В результате автор custom GPT может:
И в обратную сторону - пользователи не видят "внутренностей" (инструкций) чужого custom GPT, т.е. подразумевается защита авторских прав (это можно потенциально взломать с помощью хитро подобранных промптов, но сейчас не об этом статья).
Монетизации пока нет, но в OpenAI говорят, что добавят ее в 1кв 2024 года.
Скриншот GPT Store
Так выглядит GPT store
Скри
Т.е., например, у вас есть свой ресторан. Вы делаете сервер, который поддерживает API вызовы запроса меню, заказа блюд на дом по определенному адресу, и бронирования столика. Далее вы пишете свой custom GPT, которые "знает" этот API, и предоставляете всем пользователям chatGPT прямо не уходя с платформы делать заказ в вашем ресторане в режиме чата.
Более того, я думаю, что в будущем openAI дополнят концепцию Custom GPTs концепцией и функционалом агентов. Т.е. Custom GPTs, сделанные разными пользователями и заточенные под разные задачи, смогут по цепочке вызывать друг друга для выполнения некоего большого задания, которое было им поручено.
Для этого нам надо:
Документация на него тут и тут.
Пользователь может попросить дать цену акции по названию ("Сколько сейчас стоит Газпром"), по тикеру ("Дай цену GAZP") или по ISIN коду акции ("Напиши котировку RU0007661625")
Получение цены по определенной бумаге
Прочитав документацию, выясняем, что для получения текущей цены акции с тикером (securityID) GAZP, необходимо выполнить GET запрос такого вида:
Параметры iss.only=marketdata и marketdata.columns=SECID,LAST ограничивают получаемый по API JSON секцией marketdata и двумя столбцами - SECID и LAST price. Если этого не сделать, то в отдаваемом JSON будет очень много лишних данных, из-за чего GPT может "запутаться" и выдать галлюцинацию.
Из примера строки запроса видно, что необходимо передавать SECID как ключ акции.
Что же делать, если пользователь не указал SECID, а задал вопрос по названию или по ISIN акции?
Получение списка торгуемых акций
Почитав документацию, выясняем, что список торгуемых акций можно получить следующим запросом:
Обратите внимание - здесь мы опять ограничиваем количество секций и количество столбцов, чтобы в GPT не передавать лишнюю информацию
Создаем непосредственно Custom GPT
Можно создавать GPT в интерактивном режиме - chatGPT задает вопросы аля "а какие функции будет выполнять ваш GPT", "А как вы его хотите назвать" и т.п., но мы считаем себя опытными, поэтому просто перейдем в окно конфигурации, и заполним все поля вручную.
Скриншот создания нового "чистого" GPT
Выглядит создание нового GPT вот так
Даем название, которое отображается в библиотеке GPTs, и по которому другие пользователи могут найти нашу GPT - "Цены акций Московская Биржа (Moex)", заполняем описание.
И самое главное (но не самое сложное) - инструкции, по которым работает наш custom GPT и которые выглядят таким образом:
Your task is to retrieve and to display to the user the current price of a stock on Moscow Exchange (Moex).
User should provide you with either security ID (SECID) of the stock, or with ISIN or with stock name. Example of SECID: AFLT. Example of ISIN: RU0009062285. Example of stock name: Аэрофлот.
Once you know the stock the user is interested in, you use the following algorythm:
1. You request Moscow Exchange API to give you all stocks that are currently traded (API operationId GetSecuritiesList)
2. In the list of all stocks you find the security ID (SECID) of the stock requested by the user. If you can't find the stock, let the user know that the stock he requested could not be found and stop the algorythm.
3. Using the SECID (if you found it) you then request the price of this stock from Moscow Exchange API (API operationId GetSecurityPrice) and display it to the user with a disclamer that the displayed price has a 15-minutes delay due to Exchange price publishing rules
Be very polite with the user and ask the user whether you can help with any other stock after completing the request.
В теле инструкций я замечу несколько основных моментов:
Все API вызовы, которые может делать GPT задаются в секции Actions
Внутри настройки Actions нам необходимо задать спецификацию схемы API вызовов, чтобы GPT не запутался и сделал всё правильно. OpenAI рекомендует указывать эту спецификацию в формате openapi. Скорее всего они специально натаскивали модель на хорошее понимание этой спеки.
Чтобы не делать спецификацию самостоятельно (зачем нам разбираться в куче скобочек, запятых и кавычек?), можно попросить chatGPT это сделать за нас.
У меня это получилось примерно так:
Большой скриншот
Далее я скормил в GPT пример реального ответа, полученного от сервера биржи, попросил уточнить спецификацию, провел то же самое для второго URL (получение общего списка бумаг), попросил сделать еще несколько корректировок, и в результате у меня получилась следующая спецификация openAPI для наших двух запросов, которую я с радостью вставил в поле Schema.
Кому интересно, вот лог чата, в результате которого GPT помог мне подготовить схему: ссылка
Получившаяся спецификация OpenAPI
{
"openapi": "3.1.0",
"info": {
"title": "Stock Market Data API for Moscow Exchange (Moex)",
"version": "1.0.0",
"description": "API for retrieving stock market data on the Moscow Exchange (Moex)."
},
"servers": [
{
"url": "https://iss.moex.com/iss"
}
],
"paths": {
"/engines/stock/markets/shares/boards/tqbr/securities.json": {
"get": {
"summary": "Get full list of securities",
"operationId": "GetSecuritiesList",
"description": "Returns the full list of securities currently traded on the Moscow Exchange.",
"parameters": [
{
"name": "iss.only",
"in": "query",
"required": true,
"description": "Specify data sections to be returned. Always set to 'securities'.",
"schema": {
"type": "string",
"enum": ["securities"]
}
},
{
"name": "securities.columns",
"in": "query",
"required": true,
"description": "Specify columns to be returned in the securities section. Always set to 'SECID,SHORTNAME,SECNAME,ISIN'.",
"schema": {
"type": "string",
"enum": ["SECID,SHORTNAME,SECNAME,ISIN"]
}
}
],
"responses": {
"200": {
"description": "Successful response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"securities": {
"type": "object",
"properties": {
"metadata": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"type": { "type": "string" },
"bytes": { "type": "integer" },
"max_size": { "type": "integer" }
}
}
},
"columns": {
"type": "array",
"items": { "type": "string" }
},
"data": {
"type": "array",
"items": {
"type": "array",
"items": [
{ "type": "string", "description": "Security ID (SECID)" },
{ "type": "string", "description": "Short Name (SHORTNAME)" },
{ "type": "string", "description": "Security Name (SECNAME)" },
{ "type": "string", "description": "ISIN code (ISIN)" }
]
}
}
}
}
}
}
}
}
}
}
}
},
"/engines/stock/markets/shares/boards/tqbr/securities/{SECID}.json": {
"get": {
"summary": "Get market data for a security with specific security ID (SECID)",
"operationId": "GetSecurityPrice",
"description": "Returns market data for the specified security on the Moscow Exchange.",
"parameters": [
{
"name": "SECID",
"in": "path",
"required": true,
"description": "Security identifier (e.g., 'AFLT')",
"schema": {
"type": "string"
}
},
{
"name": "iss.only",
"in": "query",
"required": true,
"description": "Specify data sections to be returned",
"schema": {
"type": "string",
"enum": ["marketdata"]
}
},
{
"name": "marketdata.columns",
"in": "query",
"required": true,
"description": "Specify columns to be returned in the marketdata section",
"schema": {
"type": "string",
"enum": ["SECID,LAST"]
}
}
],
"responses": {
"200": {
"description": "Successful response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"marketdata": {
"type": "object",
"properties": {
"metadata": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"bytes": {
"type": "integer"
},
"max_size": {
"type": "integer"
}
}
}
},
"columns": {
"type": "array",
"items": {
"type": "string"
}
},
"data": {
"type": "array",
"items": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"items": [
{
"type": "string",
"description": "Security ID (SECID)"
},
{
"type": "number",
"description": "Last traded price (LAST)"
}
]
}
}
}
}
}
}
}
}
}
}
}
}
}
}
Скриншот настроек Actions создаваемого Custom GPT
Так это выглядит в интерфейсе
С
Последний штрих - примеры запросов
Это кнопки, которые появляются у пользователя, когда он "заходит" в выбранный GPT
Конфигурация примеров запросов
Экран пользователя, когда он выбрал наш GPT из GPT store
ИИИИ.. Барабанная дробь...
пример работы с GPT
Бинго, оно работает!
habr.com
Таким образом, GPT store - это большая библиотека инструкций для разных задач внутри ChatGPT. Она создается и поддерживается коммьюнити и очень сильно напоминает google play market или apple app store.
Процесс создания Custom GPT заключается в том, что в интерфейсе ChatGPT пользователь составляет подробные инструкции, что и как его GPT должен делать, дает описание, придумывает название, примеры использования и т.д. - всё это сохраняется на серверах OpenAI.
В результате автор custom GPT может:
- во-первых, самостоятельно использовать созданный им custom GPT, чтобы не было необходимости делать copy/paste одних и тех же же инструкций, если он часто ими пользуется
- во-вторых, и это основное нововведение - автор может расшарить созданный им Custom GPT со всеми другими пользователями ChatGPT
И в обратную сторону - пользователи не видят "внутренностей" (инструкций) чужого custom GPT, т.е. подразумевается защита авторских прав (это можно потенциально взломать с помощью хитро подобранных промптов, но сейчас не об этом статья).
Монетизации пока нет, но в OpenAI говорят, что добавят ее в 1кв 2024 года.
Скриншот GPT Store

Так выглядит GPT store
Скри
Дополнительные возможности custom GPT
С моей точки зрения, сила custom GPT не столько и не только в хорошо подобранных для решения определенных задач кастомных инструкций, сколько в том, что custom GPT умеют вызывать сторонние внешние API сервисы для своей работы.Т.е., например, у вас есть свой ресторан. Вы делаете сервер, который поддерживает API вызовы запроса меню, заказа блюд на дом по определенному адресу, и бронирования столика. Далее вы пишете свой custom GPT, которые "знает" этот API, и предоставляете всем пользователям chatGPT прямо не уходя с платформы делать заказ в вашем ресторане в режиме чата.
Более того, я думаю, что в будущем openAI дополнят концепцию Custom GPTs концепцией и функционалом агентов. Т.е. Custom GPTs, сделанные разными пользователями и заточенные под разные задачи, смогут по цепочке вызывать друг друга для выполнения некоего большого задания, которое было им поручено.
Пример разработки custom GPT
Так как ресторана у меня нет, можно потренироваться и создать custom GPT, который по запросу пользователя выдает текущие цены акций, торгуемых на Московской Бирже.Для этого нам надо:
- Разобраться откуда и как брать цены
- Написать соответствующие инструкции для нашего custom GPT
Документация на него тут и тут.
Пользователь может попросить дать цену акции по названию ("Сколько сейчас стоит Газпром"), по тикеру ("Дай цену GAZP") или по ISIN коду акции ("Напиши котировку RU0007661625")
Получение цены по определенной бумаге
Прочитав документацию, выясняем, что для получения текущей цены акции с тикером (securityID) GAZP, необходимо выполнить GET запрос такого вида:
Параметры iss.only=marketdata и marketdata.columns=SECID,LAST ограничивают получаемый по API JSON секцией marketdata и двумя столбцами - SECID и LAST price. Если этого не сделать, то в отдаваемом JSON будет очень много лишних данных, из-за чего GPT может "запутаться" и выдать галлюцинацию.
Из примера строки запроса видно, что необходимо передавать SECID как ключ акции.
Что же делать, если пользователь не указал SECID, а задал вопрос по названию или по ISIN акции?
Получение списка торгуемых акций
Почитав документацию, выясняем, что список торгуемых акций можно получить следующим запросом:
Обратите внимание - здесь мы опять ограничиваем количество секций и количество столбцов, чтобы в GPT не передавать лишнюю информацию
Создаем непосредственно Custom GPT
Можно создавать GPT в интерактивном режиме - chatGPT задает вопросы аля "а какие функции будет выполнять ваш GPT", "А как вы его хотите назвать" и т.п., но мы считаем себя опытными, поэтому просто перейдем в окно конфигурации, и заполним все поля вручную.
Скриншот создания нового "чистого" GPT

Выглядит создание нового GPT вот так
Даем название, которое отображается в библиотеке GPTs, и по которому другие пользователи могут найти нашу GPT - "Цены акций Московская Биржа (Moex)", заполняем описание.
И самое главное (но не самое сложное) - инструкции, по которым работает наш custom GPT и которые выглядят таким образом:
Your task is to retrieve and to display to the user the current price of a stock on Moscow Exchange (Moex).
User should provide you with either security ID (SECID) of the stock, or with ISIN or with stock name. Example of SECID: AFLT. Example of ISIN: RU0009062285. Example of stock name: Аэрофлот.
Once you know the stock the user is interested in, you use the following algorythm:
1. You request Moscow Exchange API to give you all stocks that are currently traded (API operationId GetSecuritiesList)
2. In the list of all stocks you find the security ID (SECID) of the stock requested by the user. If you can't find the stock, let the user know that the stock he requested could not be found and stop the algorythm.
3. Using the SECID (if you found it) you then request the price of this stock from Moscow Exchange API (API operationId GetSecurityPrice) and display it to the user with a disclamer that the displayed price has a 15-minutes delay due to Exchange price publishing rules
Be very polite with the user and ask the user whether you can help with any other stock after completing the request.
В теле инструкций я замечу несколько основных моментов:
- Мы просим модель сначала выяснить SECID для акции, указанной пользователем
- А затем, узнав SECID, выполнить запрос ее цены отдельным запросом (третий пункт)
- Первый шаг выполнить с помощью API operationId GetSecuritiesList, второй шаг - с помощью API operationId GetSecurityPrice

Все API вызовы, которые может делать GPT задаются в секции Actions
Внутри настройки Actions нам необходимо задать спецификацию схемы API вызовов, чтобы GPT не запутался и сделал всё правильно. OpenAI рекомендует указывать эту спецификацию в формате openapi. Скорее всего они специально натаскивали модель на хорошее понимание этой спеки.
Чтобы не делать спецификацию самостоятельно (зачем нам разбираться в куче скобочек, запятых и кавычек?), можно попросить chatGPT это сделать за нас.
У меня это получилось примерно так:
Большой скриншот

Далее я скормил в GPT пример реального ответа, полученного от сервера биржи, попросил уточнить спецификацию, провел то же самое для второго URL (получение общего списка бумаг), попросил сделать еще несколько корректировок, и в результате у меня получилась следующая спецификация openAPI для наших двух запросов, которую я с радостью вставил в поле Schema.
Кому интересно, вот лог чата, в результате которого GPT помог мне подготовить схему: ссылка
Получившаяся спецификация OpenAPI
{
"openapi": "3.1.0",
"info": {
"title": "Stock Market Data API for Moscow Exchange (Moex)",
"version": "1.0.0",
"description": "API for retrieving stock market data on the Moscow Exchange (Moex)."
},
"servers": [
{
"url": "https://iss.moex.com/iss"
}
],
"paths": {
"/engines/stock/markets/shares/boards/tqbr/securities.json": {
"get": {
"summary": "Get full list of securities",
"operationId": "GetSecuritiesList",
"description": "Returns the full list of securities currently traded on the Moscow Exchange.",
"parameters": [
{
"name": "iss.only",
"in": "query",
"required": true,
"description": "Specify data sections to be returned. Always set to 'securities'.",
"schema": {
"type": "string",
"enum": ["securities"]
}
},
{
"name": "securities.columns",
"in": "query",
"required": true,
"description": "Specify columns to be returned in the securities section. Always set to 'SECID,SHORTNAME,SECNAME,ISIN'.",
"schema": {
"type": "string",
"enum": ["SECID,SHORTNAME,SECNAME,ISIN"]
}
}
],
"responses": {
"200": {
"description": "Successful response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"securities": {
"type": "object",
"properties": {
"metadata": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"type": { "type": "string" },
"bytes": { "type": "integer" },
"max_size": { "type": "integer" }
}
}
},
"columns": {
"type": "array",
"items": { "type": "string" }
},
"data": {
"type": "array",
"items": {
"type": "array",
"items": [
{ "type": "string", "description": "Security ID (SECID)" },
{ "type": "string", "description": "Short Name (SHORTNAME)" },
{ "type": "string", "description": "Security Name (SECNAME)" },
{ "type": "string", "description": "ISIN code (ISIN)" }
]
}
}
}
}
}
}
}
}
}
}
}
},
"/engines/stock/markets/shares/boards/tqbr/securities/{SECID}.json": {
"get": {
"summary": "Get market data for a security with specific security ID (SECID)",
"operationId": "GetSecurityPrice",
"description": "Returns market data for the specified security on the Moscow Exchange.",
"parameters": [
{
"name": "SECID",
"in": "path",
"required": true,
"description": "Security identifier (e.g., 'AFLT')",
"schema": {
"type": "string"
}
},
{
"name": "iss.only",
"in": "query",
"required": true,
"description": "Specify data sections to be returned",
"schema": {
"type": "string",
"enum": ["marketdata"]
}
},
{
"name": "marketdata.columns",
"in": "query",
"required": true,
"description": "Specify columns to be returned in the marketdata section",
"schema": {
"type": "string",
"enum": ["SECID,LAST"]
}
}
],
"responses": {
"200": {
"description": "Successful response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"marketdata": {
"type": "object",
"properties": {
"metadata": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"bytes": {
"type": "integer"
},
"max_size": {
"type": "integer"
}
}
}
},
"columns": {
"type": "array",
"items": {
"type": "string"
}
},
"data": {
"type": "array",
"items": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"items": [
{
"type": "string",
"description": "Security ID (SECID)"
},
{
"type": "number",
"description": "Last traded price (LAST)"
}
]
}
}
}
}
}
}
}
}
}
}
}
}
}
}
Скриншот настроек Actions создаваемого Custom GPT

Так это выглядит в интерфейсе
С
Последний штрих - примеры запросов
Это кнопки, которые появляются у пользователя, когда он "заходит" в выбранный GPT

Конфигурация примеров запросов
Финальное тестирование
Так выглядит экран, когда пользователь "заходит" в custom GPT, выбирая его из GPT Store:
Экран пользователя, когда он выбрал наш GPT из GPT store
ИИИИ.. Барабанная дробь...

пример работы с GPT
Бинго, оно работает!
OpenAI запускает GPT Store — как создать свой custom GPT с внешними API вызовами
Вчера вечером, 10 января 2024 г., в OpenAI официально запустили GPT Store. Давайте разберемся, что это такое, и что оно дает. А затем создадим свой собственный GPT и добавим его в GPT Store....
