Future AI Today
Рассказываем новости искусственного интелекта. Находим и обозреваем полезные нейросервисы.

Время создать личный чат-бот на базе ChatGPT.

Пошаговое руководство по созданию веб чат-бота на базе API gpt-3.5-turbo на Python

Время создать личный чат-бот на базе ChatGPT.

Зачем это нужно?

Во-первых, трудности с входом и использованием бесплатной версии ChatGPT из-за ее высокого ежедневного трафика.

Во-вторых, PRO версия доступна по цене 20 USD в месяц - мягко говоря нерентабельно для индивидуального использования. Оплата по мере использования будет ощутимо выгоднее. Однако ChatGPT не предлагает такой возможности. Зато такую модель оплаты предлагает API Open AI.

Chat Completion API (оно же ChatGPT API) использует модели GPT-3.5-turbo по цене 0.002 USD за 1000 токенов. Это представляется более экономичным вариантом использования, кроме того, доступ к API более стабилен и не имеет проблем с пиковым трафиком.

Но у ChatGPT API нет веб интерфейса, его невозможно использовать в броузере, как обычный ChatGPT - вот этот изъян мы сейчас и исправим.

C мотивацией всё, начнем.

Создайте ключ API OpenAI в панели управления Open AI по адресу https://platform.openai.com/account/api-keys.

Если вы уже создавали OpenAI API Key в своем аккаунте, вы можете продолжать использовать этот ключ вместо того, чтобы генерировать новый.

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

Chat Completion API.

API ChatGPT" называется Chat completion, документацию доступна здесь: https://platform.openai.com/docs/guides/chat/introduction. Использование API простое, даже если у вас нет опыта программирования.

Чтобы получить ответ от API нужно:

Установить python пакет

pip install openai

Импортировать модуль

import openai

Создать и отправить запрос


import openai

openai.api_key = '__OPEN_AI_API_KEY__'

complete = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Кто такой Руаль Амундсен?"},
        {"role": "assistant", "content": "Руаль Амундсен это первый человек, достигший Южного полюса 14 декабря 1911 года."},
        {"role": "user", "content": "На каком острове зимовал Руаль Амундсен когда путешествовал к южному полюсу?"}
    ]
)
message = complete.choices[0].message.content

print(message)

и получаем вот такой ответ


Руаль Амундсен зимовал на острове Росса в западной части Россового моря, прежде чем начать свою экспедицию к южному полюсу.

Process finished with exit code 0

Как видно в коде мы используем более многословную форму общения с API нежели чем с ChatGPT - вместо прямого вопроса используется своеобразный диалог. Разберем его подробнее.

system, user и assistant- это три роли, определенные в объекте сообщения. Они настраивают поведение API в ходе диалога.

  • system определяется основной паттерн поведения чат-бота путем добавления инструкции в содержимое.
  • user представляет собой запрос от пользователя.
  • assistant относится к соответствующему ответу от API GPT-3.5.

Этот диалоговый обмен имитирует разговор, при этом сообщение user инициирует взаимодействие, а сообщение assistent предоставляет релевантный и информативный ответ, чтобы дать модели чат-бота контекст этого разговора для создания более релевантного ответа позже.

Таким образом мы даем понять модели о каком именно Аммудсене идет речь - о первом человеке, достигшем Южного полюса. В результате задания такого контекста мы получаем релевантный ответ на наш основной вопрос - на каком острове была зимовка.

Пока наше приложение не имеет ничего общего с привычным интерфейсом чат-бота, пришло время это исправить. В этом поможет специализированный фреймворк Streamlit, созданный для упрощения разработки интерфейсов ML приложений.

Streamlit и Streamlit_chat

Streamlit и Streamlit_chat

Streamlit - это фреймворк с открытым исходным кодом, который позволяет специалистам по исследованию данных и разработчикам быстро создавать интерактивные веб-приложения для проектов в области машинного обучения и науки о данных. Для нашей цели создания простого веб чат-бота, Streamlit является вполне подходящей библиотекой в паре с библиотекой Streamlit_chat, которая обеспечивает дополнительное удобство для создания чатов. Документация: https://docs.streamlit.io/

Чтобы создать Streamlit сайт, достаточно выполнить всего несколько шагов:

Установить пакет

pip install streamlit

Создайте вот такой файл Python chat.py


import streamlit as st

st.write("""
# My First App
Hello *world!*
""")

Запустить командой

python -m streamlit run chat.py

Вывод команды сообщает адрес запущенного сайта


Welcome to Streamlit!

If you’d like to receive helpful onboarding emails, news, offers, promotions,
and the occasional swag, please enter your email address below. Otherwise,
leave this field blank.

Email:

You can find our privacy policy at https://streamlit.io/privacy-policy

Summary:
- This open source library collects usage statistics.
- We cannot see and do not store information contained inside Streamlit apps,
such as text, charts, images, etc.
- Telemetry data is stored in servers in the United States.
- If you'd like to opt out, add the following to ~/.streamlit/config.toml,
creating that file if necessary:

[browser]
gatherUsageStats = false

You can now view your Streamlit app in your browser.

Local URL: http://localhost:8501
Network URL: http:/127.0.0.1:8501

Получившийся сайт выглядит вот так:

Streamlit site

Объединяем Open AI API и сайт на Streamlit в приложение chat.py

Теперь доделаем наше приложение. Сделать это так же просто, как и нарисовать сову, надо просто добавить недостающие детали.

ChatGPT Дома

Все рабочие данные для операций управляются объектом session_state из Streamlit. Мы определили список prompt-ов для хранения сообщений, которые начинаются с сообщения роли system и уточняются ролями user и assistant.

Еще два session_state используются для хранения всех ответов API и всех prompt-ов пользователя для отображения парами в стиле чата с помощью функции Streamlit_chat message().

Есть две кнопки, созданные виджетом Streamlit, Send для отправки запроса ChatCompletion и New Chat для очистки истории чата. Их поведение определено в callback функциях chat_click() и end_click().

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

В итоге получается вот такой код в chat.py, его можно скопировать и использовать, только надо заменить __API_KEY__ и __LOGO_PATH__ на свои.


import openai
import streamlit as st
from streamlit_chat import message

openai.api_key = '__API_KEY__'

if 'prompts' not in st.session_state:
    st.session_state['prompts'] = [{"role": "system",
                                    "content": "You are a helpful assistant. Answer as concisely as possible with a little humor expression."}]
if 'generated' not in st.session_state:
    st.session_state['generated'] = []
if 'past' not in st.session_state:
    st.session_state['past'] = []


def generate_response(prompt):
    st.session_state['prompts'].append({"role": "user", "content": prompt})
    completion = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=st.session_state['prompts']
    )

    message = completion.choices[0].message.content
    return message


def end_click():
    st.session_state['prompts'] = [{"role": "system",
                                    "content": "You are a helpful assistant. Answer as concisely as possible with a little humor expression."}]
    st.session_state['past'] = []
    st.session_state['generated'] = []
    st.session_state['user'] = ""


def chat_click():
    if st.session_state['user'] != '':
        chat_input = st.session_state['user']
        output = generate_response(chat_input)
        # store the output
        st.session_state['past'].append(chat_input)
        st.session_state['generated'].append(output)
        st.session_state['prompts'].append({"role": "assistant", "content": output})
        st.session_state['user'] = ""


st.image('__LOGO_PATH__', width=64)
st.title("ChatGPT Дома")

user_input = st.text_input("You:", key="user")

chat_button = st.button("Send", on_click=chat_click)
end_button = st.button("New Chat", on_click=end_click)

if st.session_state['generated']:
    for i in range(len(st.session_state['generated']) - 1, -1, -1):
        tab1, tab2 = st.tabs(["normal", "rich"])
        with tab1:
            message(st.session_state['generated'][i], key=str(i))
        with tab2:
            st.markdown(st.session_state['generated'][i])
        message(st.session_state['past'][i], is_user=True, key=str(i) + '_user')

Запускаем, проверяем

python -m streamlit run chat.py

ChatGPT Дома

ChatGPT Дома готов!