Пошаговое руководство по демонстрации ваших моделей в Интернете (бесплатно)

Доступ к мощным моделям больших языков от OpenAI, Google и других компаний теперь проще, чем когда-либо. Используя эти современные модели, разработчики могут экспериментировать и создавать мощные приложения. Одним из способов удобного развертывания и демонстрации ваших моделей в Интернете является Streamlit (не требуется HTML или JavaScript).

В этой статье я покажу, как создать и развернуть приложение с помощью Streamlit. Для этого проекта я создал простое приложение, которое суммирует онлайн-статьи или сообщения в блогах, используя языковую модель Google Pegasus с платформы Hugging Face.

Вы можете проверить код на GitHub и попробовать приложение здесь.

Что такое стримлит?

Streamlit — это библиотека Python с открытым исходным кодом, которая позволяет создавать интерактивные веб-приложения с некоторыми изменениями в существующем сценарии Python. Кроме того, Streamlit предлагает бесплатный хостинг, где вы можете развернуть свое приложение с GitHub.

Streamlit совместим с несколькими библиотеками и фреймворками, такими как Pandas, Matplotlib, Scikitlearn, Pytorch, TensorFlow и другими.

Начиная

Установите пакет в свою среду через pip (рекомендуется предварительно настроить виртуальную среду, см. руководство здесь):

$ pip install streamlit

Позже нам нужно будет создать файл requirements.txt, один из способов сделать это с помощью пакета pipreqs, поэтому давайте установим его заранее:

$ pip install pipreqs

Создайте новый файл Python с помощью выбранной вами IDE и начните с импорта всех необходимых библиотек. В зависимости от специфики вашего проекта просто импортируйте необходимые библиотеки, как обычно.

import streamlit as st
import json
import requests
import time
from newspaper import Article

Текстовые элементы

Приложения Streamlit — это просто скрипты Python, которые выполняются сверху вниз. Он имеет множество элементов пользовательского интерфейса (называемых виджетами), например, эта строка кода будет отображать заголовок моего приложения:

st.title("FastNews Article Summarizer")

Вы можете отображать текст в формате Заголовок, формат Подзаголовок и даже Markdown:

st.markdown("**Generate summaries of online articles using abstractive summarization with Google's PEGASUS model.**")
st.subheader("Enter the URL of the article you want to summarize")

Чтобы проверить, как выглядит ваше приложение, выполните эту команду в терминале (сохраните все изменения файла перед запуском команды):

$ streamlit run your_app.py

Окно браузера запустится локально, отображая ваше приложение:

Входные элементы

Мое приложение требует, чтобы пользователь ввел URL-адрес. Для этой цели мы можем присвоить виджет st.text_input() переменной и обрабатывать ее как любую другую переменную в Python:

default_url = "https://"
url = st.text_input("URL:", default_url)

С помощью st.button("Fetch article") мы создаем кнопку, которую пользователь будет нажимать после ввода URL-адреса.

Помимо URL-адреса статьи, мое приложение требует, чтобы пользователь ввел действительный ключ API от HuggingFace, и я хочу замаскировать этот текст для обеспечения конфиденциальности. Для этого мы просто передаем аргумент type="password" виджету st.text_input():

API_KEY = st.text_input("Enter your HuggingFace API key", type="password")

Как только пользователь введет ключ API, кнопка st.button("Submit") запустит извлечение статьи, затем отправит запрос в конечную точку API Hugging Face и, наконец, отобразит результаты.

Извлечение статей из Интернета

  1. Используйте библиотеку requests, чтобы очистить содержимое статьи от ее URL-адреса.
  2. Затем, используя библиотеку newspaper, проанализируйте очищенный HTML и извлеките текст из статьи.

Чтобы реализовать Шаг 1, следующий блок кода будет выполнен, если была нажата кнопка "Получить статью":

headers_ = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'
    }

if fetch_button:
    article_url = url
    session = requests.Session()

    try:
        response_ = session.get(article_url, headers=headers_, timeout=10)
    
        if response_.status_code == 200:

            with st.spinner('Fetching your article...'):
                time.sleep(3)
                st.success('Your article is ready for summarization!')

        else:
            st.write("Error occurred while fetching article.")

    except Exception as e:
        st.write(f"Error occurred while fetching article: {e}")

Этот блок try-except обрабатывает исключения, которые могут возникнуть при получении статьи. Метод requests.get отправляет HTTP-запрос GET на URL-адрес с указанными заголовками и временем ожидания. Если код состояния ответа равен 200 (указывающий на успешный запрос), выполняется оператор if. В противном случае мы используем виджет st.write() для отображения сообщения об ошибке. Если во время запроса возникает какое-либо исключение, выполняется оператор except и отображается ошибка исключения (сохраненная в переменной e).

Виджет st.spinner() внутри оператора if создает счетчик загрузки с сообщением "Выбор статьи...". Наконец, виджет st.success() отображает сообщение об успешном завершении "Ваша статья готова к обобщению!"

Для шага 2 мы используем класс Article из библиотеки newspaper:

if submit_button:
    article = Article(url)
    article.download()
    article.parse()

    title = article.title
    text = article.text

Эти строки извлекают заголовок и текст статьи, используя атрибуты title и text объекта article.

API для определения лица в объятиях

Hugging Face – это сообщество ИИ, в котором размещаются модели ML с открытым исходным кодом, в которых особое внимание уделяется преобразователям для обработки естественного языка (NLP). Изобретение архитектуры Transformer в 2017 году произвело революцию в области НЛП. Преобразователь сделал возможным создание LLM, таких как GPT, BERT, T5 и многих других.

Я буду использовать модель Pegasus из центра Hugging Face. Pegasus — это преобразователь в стиле кодер-декодер, предварительно обученный для суммирования. Конкретная контрольная точка: google/pegasus-cnn_dailymail, точно настроенная с корпусом CNN-dailymail.

Запустить модель из размещенного API вывода довольно просто. Я буду использовать бесплатную конечную точку API вывода:

API_URL = "https://api-inference.huggingface.co/models/google/pegasus-cnn_dailymail"

Чтобы сделать запрос, мы определяем «заголовок», который содержит ключ API пользователя, ранее сохраненный в переменной API_KEY:

headers = {"Authorization": f"Bearer {API_KEY}"}

Далее функция query отправит запрос POST на конечную точку API. Извлеченный текст из статьи будет отправлен в формате JSON. После получения ответа функция возвращает содержимое JSON с помощью метода response.json(). Этот метод преобразует ответ JSON в объект Python, к которому можно легко получить доступ и которым можно легко манипулировать.

def query(payload):
    response = requests.post(API_URL, headers=headers, json=payload)
    return response.json()

Наконец, мы отправляем наш запрос, передавая переменную text в качестве аргумента, и сохраняем чистый сводный текст в переменной summary. Обратите внимание, что мы заменили строку <n>, которая является особым способом представления токенов пустого пространства в нашей модели:

        output = query({"inputs": text, })

       # Display the results
        summary = output[0]['summary_text'].replace('<n>', " ") 

        st.divider()
        st.subheader("Summary")
        st.write(f"Your article: **{title}**")
        st.write(f"**{summary}**")

Сводка отображается с помощью виджета st.write(). Текст в этом виджете также можно рассматривать как текст Markdown.

Последние штрихи

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

c1, c2 = st.columns([0.32, 2])

with c1:
     st.image("images/newspaper.png", width=85)

with c2:
    st.title("FastNews Article Summarizer")

Столбцы c1 и c2 создаются с помощью виджета st.columns(), c1 шириной 0,32 и c2 вдвое больше этого значения.

Для виджета st.image() требуется локальный путь к файлу изображения или URL-адрес изображения. В этом случае я также установил ширину изображения на 85 пикселей.

Наконец, давайте добавим раздел боковой панели, где я хочу отображать некоторую информацию о приложении. Это легко сделать с помощью объекта st.sidebar следующим образом:

st.sidebar.subheader("About the app")
st.sidebar.info("This app uses 🤗HuggingFace's [google/pegasus-cnn_dailymail](https://huggingface.co/google/pegasus-cnn_dailymail) model.\
                 \nYou can find the source code [here](https://github.com/ivnlee/streamlit-text-summarizer)")
st.sidebar.write("\n\n")
st.sidebar.markdown("**Get a free API key from HuggingFace:**")
st.sidebar.markdown("* Create a [free account](https://huggingface.co/join) or [login](https://huggingface.co/login)")
st.sidebar.markdown("* Go to **Settings** and then **Access Tokens**")
st.sidebar.markdown("* Create a new Token (select 'read' role)")
st.sidebar.markdown("* Paste your API key in the text box")
st.sidebar.divider()
st.sidebar.write("Please make sure your article is in English and is not behind a paywall.")
st.sidebar.write("\n\n")
st.sidebar.divider()
st.sidebar.caption("Created by [Ivan Lee](https://ivan-lee.medium.com/) using [Streamlit](https://streamlit.io/)🎈.")

Виджет st.info() отображает информационное сообщение, а st.caption() используется для отображения сносок или текста примечания:

Развертывание

Чтобы развернуть приложение, сначала зарегистрируйтесь в Streamlit Cloud (вам будет предложено привязать свою учетную запись GitHub к Streamlit). Нам также необходимо создать общедоступный репозиторий GitHub, содержащий все файлы нашего проекта.

Как я упоминал ранее, нам нужен файл requirements.txt, чтобы Streamlit знал, какие зависимости необходимы для запуска приложения. В терминале перейдите в папку проекта и просто введите команду:

$ pipreqs ./

Пакет pipreqs автоматически создаст текстовый файл со списком библиотек, необходимых вашему приложению. (Обязательно загрузите все файлы на GitHub).

Как только все файлы будут в репозитории GitHub, мы готовы к развертыванию. В рабочей области Streamlit нажмите кнопку Новое приложение и выберите параметр Из существующего репозитория:

Затем введите URL-адрес репо и основной путь к файлу. URL-адрес будет автоматически назначен приложению, но его можно изменить (в зависимости от доступности). Наконец, нажмите кнопку Развернуть!:

Вот и все! через пару минут приложение будет развернуто и доступно из Интернета.

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

Спасибо за прочтение! Я надеюсь, что вы найдете эту статью полезной, не стесняйтесь делиться ею и оставлять мне свои комментарии.