В данной статье рассмотрим процесс создания прототипа бота с использованием ChatGPT 3.5 API от OpenAI для участия в текстовой игре Great Wyrm на блокчейне, разработанной Moonstream.to. Готовый код вы можете найти в репозитории kompotkot/gofp-chatgpt-bot.

Great Wyrm session
Great Wyrm session

Great Wyrm представляет собой платформу для организации игровых сессий в формате "гейм-мастер - игроки". В настоящее время игра находится на стадии активного тестирования, и создатели платформы самостоятельно проводят игровые сессии. Работает платформа в блокчейн сети wyrm.constellation от Caldera. Для участия вы можете зарегистрироваться в дискорде по ссылке.

Код будет написан на языке Python. Так как игра разработана на базе блокчейна Ethereum, для взаимодействия с сетью мы будем использовать библиотеку brownie, а для генерации Python-интерфейса из ABI - библиотеку moonworm.

Обычно для популярных игр ABI можно найти на Etherscan во вкладке "Code", на GitHub проекта или сгенерировать самостоятельно из .sol файлов с использованием инструментов, таких как brownie. Для игры Great Wyrm контракт доступен по ссылке на GitHub, а подготовленный ABI можно найти в документации Moonstream docs.

Однако, имея только ABI, нам необходимо воссоздать структуру brownie для корректной работы. Для этого создадим необходимые папки, скопируем ABI:

mkdir -p gcb/build/contracts/
cp abi/GOFP.json gcb/build/contracts/gofp.json

Наш gcb/build/contracts/gofp.json должен выглядеть следующим образом:

{
  "abi": [
    ...
  ]
}

Сгенерируем интерфейс по нашему ABI, что создаст Python файл gcb/gofp.py с классом gofp и методами описывающими функционал смартконтракта:

moonworm generate-brownie --name gofp -o gcb -p gcb

Далее нам потребуется добавить блокчейн wyrm в локальный список сетей brownie:

brownie networks add Constellation wyrm host=https://wyrm.0xconstellation.com/http chainid=322

Первая часть готова, теперь мы можем общаться со смарткотрактом, только лишь добавим необходимую переменную:

export GOFP_CONTRACT_ADDRESS="0x42A8E82253CD19EF8274D48fC0bC89cdf1B4425b"

Спросим у смартконтракта, сколько всего проведено игровых сессий:

python -m gcb.gofp num-sessions --network wyrm --address "$GOFP_CONTRACT_ADDRESS"

Теперь перейдем к настройке ChatGPT. Для этого нам потребуется API-ключ, сгенерированный на сайте OpenAI, который позволит общаться с платформой. Добавим этот ключ в код, используя переменную:

export OPENAI_API_KEY="sk-..."

Протестируем функционал, например спросим доступные нам GPT модели для работы:

curl https://api.openai.com/v1/models -H "Authorization: Bearer $OPENAI_API_KEY" | jq .data[].id | grep gpt

Посмотрим на структуру кода и пройдемся по основным моментам:

drwxrwxr-x build
-rw-rw-r-- cli.py
-rw-rw-r-- data.py
-rw-rw-r-- gofp.py
-rw-rw-r-- __init__.py
-rw-rw-r-- version.py
-rw-rw-r-- version.txt

В файле data.py с помощью библиотеки pydantic опишем основные структуры такие как SessionData, SessionDataStages и тд. для удобства работы. В cli.py расположился основной код.

Во время генерации CLI с помощью argparse, нам необходимо расширить парсер с пре-сгенерированными флагами и аргументами из gofp.py:

add_default_arguments(parser=parser_play, transact=True)

Далее потребуются два основных аргумента --session для указания в какой сессии играть и --token для задания с каким токеном оперировать. В основной функции handle_play сперва подключимся к сети brownie и инициализируем инстанс контракта:

network.connect(args.network)
contract = gofp(contract_address=args.address)

Благодаря библиотеки moonworm, коммуникация со смартконтрактом осуществляется через методы, получим информацию об интересующей нас сессии:

session_info_raw = contract.get_session(args.session)
...
current_stage_indexed = contract.get_current_stage(args.session)

Все, что нам остается, распарсить ответ по нашим структурам описанным в data.py и доработать логику отсекающую неактивные сессии и тд.

Каждая сессия, это своего рода токен, со своим tokenURI, где хранятся описание стадий игры, лор и тд, получим эту информацию с помощью базовой библиотеки requests реализованной в функции requests_call и так же распарсим по нашим структурам:

session_data_raw = requests_call(method=data.Method.GET, url=session_info.uri)

Теперь нам необходимо подготовить текст для ChatGPT, например в данном случае мы опишем ему что от него требуется и попросим отвечать в формате JSON, где под ключом answer он укажет выбранный им путь в игре, а в description обоснует свой выбор:

message_to_bot = f"""Let's play. I will provide you with a short lore containing 
different paths to choose from. Please respond in JSON format. You should select 
one correct path and place it under the key 'answer' and provide an explanation 
for your choice under the key 'description'.
    
The lore: {session_data.stages[current_stage].lore}
Paths:
{paths}
"""

Запросим ответ от ChatGPT. Важно указать высокое значение timeout, так как иногда ответы могут занимать продолжительное время:

openapi_headers = {
    "Authorization": f"Bearer {OPENAI_API_KEY}",
}
payload = {
    "model": "gpt-3.5-turbo",
    "messages": [{"role": "user", "content": message_to_bot}],
}

bot_resp_raw = requests_call(
    method=data.Method.POST,
    url=f"{OPENAPI_BASE_URL}/completions",
    headers=openapi_headers,
    json=payload,
    timeout=60,
)

Так же вы можете выстроить полноценную коммуникацию с ботом, OpenAI предоставляет достаточно подробные настройки доступные в документации к эндпоинту.

Получив ответ, мы его обработаем и сгенерируем транзакцию:

transaction_config = get_transaction_config(args)

tx_hash = contract.choose_current_stage_paths(
    session_id=args.session,
    token_ids=[args.token],
    paths=[bot_answer + 1],
    transaction_config=transaction_config
)

Готово. Предварительно подготовив ваш keyfile, запустить код мы сможем с помощью команды:

gcb play --address "$GOFP_CONTRACT_ADDRESS" \
  --network wyrm \
  --confirmations 0 \
  --sender "$DEV_KEYFILE" \
  --password "$DEV_KEYFILE_PASSOWRD" \
  --session 4 \
  --token 2

Бот получит все необходимые данные, распарсит результат и отчитается о транзакции:

INFO:gcb.cli:Fetch session 4 with stages [4, 1] and uri https://s3.amazonaws.com/static.greatwyrm.xyz/act1/reda_games/khina_beast_contest.json
INFO:gcb.cli:Current stage of session 4 is 1
INFO:gcb.cli:Fetch session data with title Khina's Beast Contest and active stage title Pit bat
INFO:gcb.cli:Asking ChatGPT to choose path
INFO:gcb.cli:Bot answer is: 1 and description: I would back the Copper hound because it has a useful skill that people could benefit from by sniffing out copper deposits. Additionally, they seem to be domesticated dogs so they may be more manageable than some of the other creatures. The downside is that they are not the most pleasant smelling animals and can be quite loud.
Transaction sent: 0x32bdff6127fdb94f0199f5cc10565c82fffb26768a1029f469a4b205fc5ed9fd
  Gas price: 0.0 gwei   Gas limit: 156629   Nonce: 15
  gofp.chooseCurrentStagePaths confirmed   Block: 470   Gas used: 118554 (75.69%)

<Transaction '0x32bdff6127fdb94f0199f5cc10565c82fffb26768a1029f469a4b205fc5ed9fd'>

В заключение, мы успешно разработали интеграцию между ChatGPT и Web3, создав основу для чат-бота, способного взаимодействовать с блокчейн-игрой. Эта связка предоставляет множество возможностей для дальнейшего расширения функционала и адаптации под различные задачи и цели.

Claim your reward!
Claim your reward!

Комментарии (9)


  1. Firsto
    17.04.2023 13:03
    +4

    Чувствую не за горами моды для какого-нибудь Скайрима, где можно будет с любыми неписями общаться свободно на любые темы.


    1. KompotKot Автор
      17.04.2023 13:03
      +1

      Было бы очень итересно такое пощупать, еще можно прикрутить к онлайну и с каждым диалогом прилагать идентификатор пользователя. То нпс сможет отвечать вроде "А вот твой предшественник U123456 то был похитрее и разгадал задачку, хо-хо-хо". Правда ChatGPT 3.5 сильно быстро забывает контекст :)


      1. Wotar
        17.04.2023 13:03

        На новому Маунт Блейд такий стоїть вже місяці 2-3


    1. MountainGoat
      17.04.2023 13:03
      +1

      Уже видел новости, что сделали. Только деталей не запоминал, извините.


  1. Zara6502
    17.04.2023 13:03
    +2

    администрация не хочет прикрутить фильтр чтобы статьи про ИИ можно было отключать?


    1. usernameisnotnecessary
      17.04.2023 13:03
      -1

      haters gonna hate?


      1. Zara6502
        17.04.2023 13:03
        +1

        ну ИИ не первая тема которую люди хотели бы не читать и не видеть в ленте, претензии к фильтрации я вижу например года 4, да и хейт тут ни при чем. Речь о том чтобы были не только фильтры на "я хочу этот канал", но и черные списки по словам и фразам. Ближайшие года два точно все каналы будут забиты ИИ, кому не интересна эта тема могли бы и фильтр включить. Не вижу в моих словах ненависти к чему-то.


        1. usernameisnotnecessary
          17.04.2023 13:03

          я понимаю, что не все могут быть заинтересованы в ИИ, но важно поощрять открытое обсуждение и изучение новых технологий, чтобы способствовать инновациям и прогрессу. ваш комментарий никак не относится к содержанию данной статьи. если вы недовольны фильтрацией контента на площадке, то вам стоит обратиться к администрации. я надеюсь, что вы сможете прочитать статью и принять участие в конструктивном обсуждении потенциала этой технологии.


          1. Zara6502
            17.04.2023 13:03
            +1

            весь потанцевал идет мимо РФ, у нас 3G еще не везде, так что интерес к ИИ узкоспециальный. то что он войдет в нашу жизнь без нашего желания это бесспорно, но чтением статей мы на это не повлияем.