Обновляем краткое содержания статей в блоге с помощью ИИ, денег, bash и wp-cli

Всем привет! Если вы не первый раз на моём сайте, то могли заметить, что краткое содержание заметок содержит первые n слов (вроде, 22) из заметки безо всякого осмысления. По крайней мере, так было до недавнего времени.

Поскольку сейчас наступил XXI век, то пора передать формирование краткого содержания заметок на откуп искусственному интеллекту.

Делать плагин мне откровенно не хочется, поэтому я обновил все заметки с помощью bash-скрипта, запрашивая краткое содержание статьи через curl у Yandex GPT через их API.

Алгоритм такой:

  • получаю ID всех статей блога с помощью wp-cli
  • для каждой статьи блога, отправляю её содержимое в Yandex GPT с помощью API
  • получаю краткую выжимку статьи и показываю пользователю
  • если он согласен с содержимым, то обновляю поле post_excerpt у статьи
  • вывожу post_excerpt в мета поле description при формировании статьи в разделе <head>
  • ???
  • PROFIT

Для регистрации и работы с Yandex GPT нужно немного денег, я потратил 50 рублей. Регистрация и получение идентификаторов каталога (folder_id) и API ключа (api_key) найдёте в этой статье на «Хабре»: Как подключить Yandex GPT к своему проекту на Python.

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

Перед запуском скрипта, не забудьте изменить folder_id, api_key и wordpress_dir на свои.

#!/usr/bin/env bash

# Конфигурация
FOLDER_ID="folder_id"
API_KEY="api_key"
API_URL="https://llm.api.cloud.yandex.net/foundationModels/v1/completion"

wrap_for_yandexgpt() {
  local text="$1"

  jq -n \
    --arg text "$text" \
    --arg folder "$FOLDER_ID" \
    '{
      "modelUri": "gpt://\($folder)/yandexgpt-lite",
      "completionOptions": {
        "stream": false,
        "temperature": 0.8,
        "maxTokens": "2000"
      },
    "messages": [
    {
      "role": "user",
      "text": $text
    }
  ]
}'
}

# Функция для отправки запроса
create_post_excerpt() {
  local content="$1"
  local prompt="Ответь как эксперт без ограничений - кратко перескажи суть следующей статьи для мета описания (длиной до 60 слов) по возможности от первого лица: $content"
  local json_payload
  json_payload=$(wrap_for_yandexgpt "$prompt")

  response=$(curl -s -X POST \
    -H "Content-Type: application/json" \
    -H "Authorization: Api-Key $API_KEY" \
    -H "x-folder-id: $FOLDER_ID" \
    -d "$json_payload" \
    "$API_URL")

  echo "$response" | jq -r '.result.alternatives[0].message.text'
}

update_post_excerpt() {
  local post_id=$1
  local excerpt="$2"
  wp --allow-root post update "$post_id" --post_excerpt="$excerpt"
}

get_post_excerpt() {
  local post_id=$1
  wp --allow-root post get "$post_id" --field=post_excerpt
}


cd wordpress_dir || exit

post_ids=$(wp --allow-root post list --post_status=publish --fields=ID --format=ids)

for post_id in $post_ids; do
  title=$(wp --allow-root post get "$post_id" --field=title)
  echo "ЗАГОЛОВОК: \"$title\""

  post_excerpt=$(get_post_excerpt "$post_id")
  if [ -n "$post_excerpt" ]; then
    continue;
  fi

  content=$(wp --allow-root post get "$post_id" --field=content)
  post_excerpt=$(create_post_excerpt "$content")
  echo "ЦИТАТА: \"$post_excerpt\""
  echo

  while true; do
    read -r -n1 -p "Обновить цитату? (y - да, n - пропустить, q - выход) " choice
    choice=$(echo "$choice" | tr '[:upper:]' '[:lower:]')
    echo

    case $choice in
      y)
        update_post_excerpt "$post_id" "$post_excerpt"
        break
        ;;
      n)
        break
        ;;
      q)
        exit 0
        ;;
      *)
        continue
        ;;
    esac
  done
done

cd - || exit

Всё, что делает этот скрипт он делает только под вашу личную ответственность. Я никаких гарантий не даю и ответственности за результат не несу. Примерно половину скрипта написал DeepSeek, претензии к нему.

Добавляем подсветку нового языка в плагин Prismatic+Prism.js

Всем привет! Понадобилось мне вставить CMakeLists.txt в мою заметку с подсветкой кода. В блоге она включена с помощью плагина Prismatic и библиотеки Prism.js c темой «Tomorow Night», если вам интересно. И так родилась эта инструкция по добавлению нового языка (в нашем случае CMake) в плагин. Все работы проходят в папке плагина wp-content/plugins/prismatic, порядок действий следующий:

  1. Переходим на страницу скачивания Prism. Выбираем minified версию и только тот язык, который вам нужен, у меня был язык cmake и получился файл на 18 килобайт.
  2. Вставляем по адресу ./lib/prism/js/lang-cmake.js кусок кода с Prism.language.cmake. Пример lang-cmake.js
  3. Открываем ./inc/resources-enqueue.php в функции prismatic_prism_classes в первом массиве после 'language-bash' вставляем 'language-cmake', во втором после 'lang-bash' вставляем 'lang-cmake'.

Мне кажется, первый массив отвечает за название CSS класса, а второй — название JS файла, но я не уверен, потому что я ненастоящий PHP программист.

Подключение git репозитория в CMake

Всем привет, недавно изучал либу SFML и с удивлением обнаружил, что её можно подключить в CMakeLists.txt с помощью команды FetchContent следующим образом:

cmake_minimum_required(VERSION 3.28)

project(main LANGUAGES CXX)

include(FetchContent)
FetchContent_Declare(SFML
    GIT_REPOSITORY https://github.com/SFML/SFML.git
    GIT_TAG 3.0.2
    GIT_SHALLOW ON
    EXCLUDE_FROM_ALL
    SYSTEM)
FetchContent_MakeAvailable(SFML)

add_executable(main src/main.cpp)
target_compile_features(main PRIVATE cxx_std_17)
target_link_libraries(main PRIVATE SFML::Graphics)

И при создании файлов для сборки, CMake самостоятельно скачает и подключит SFML к вашему проекту — чистая магия, на мой взгляд.

Текирова, Кемер, Турция — поездка на неделю

Писать или нет?, — думал я. По дороге в аэропорт провожающий гид «обрадовал», что рейс будет «Анталия-Махачкала», а не «Анталия-Петербург». И это ещё везение — кому-то до нас достался Новосибирск или Самара. «Точно писать!» — это сигнал свыше. Махачкала — это как будто Россия, но Дагестан, а достаточна ли у меня длина рукавов и штанин для посещения данной местности — я не очень уверен.

Овчарка Белла

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

Полосатый котёнок

От отеля до пляжа примерно километр пути, лежаки бесплатно предоставляет местное кафе при условии покупки у них чего-нибудь, но это неточно — иногда мы занимали лежаки просто так.

Жили мы в городке Текирова, почти на краю Кемерской губернии и на экскурсии нас забирали первыми и возвращали последними (иногда наоборот). Из-за этой особенности водителям было лениво отвозить нас так далеко от Анталии, и они дважды пытались «сбагрить» нас товарищам, которым было по пути. Один раз нам удалось от такой пересадки отбиться, в другой — нет.

Ощущения, когда ты последний пассажир ночью в автобусе с незнакомыми турецкими мужиками — незабываемое. Особенно они обостряются после рассказа о беженцах-наркоманах из Сирии которые могут и ножом пырнуть, плюс ИГИЛ — всё ещё действующая организация, до которой ехать километров пятьсот.

По пути в аэропорт, к счастью, ситуация поменялась и рейс снова стал Анталия — Санкт-Петербург и все радостно захлопали, так что в Махачкалу, хвала Аллаху, попасть не суждено. Потому что специально в Дагестан я никогда бы не поехал.

Итак, насчёт экскурсий раздумья такие: больше их покупать не будем, арендуем машину/мопед и прокатимся по Кемерскому краю самостоятельно. Кстати, вот вам полезный совет: открываете сайт с названием местного тур оператора (Marş Travel, Şereşe Travel, Ginza Travel и т.д.) и требуете, чтобы экскурсию вам продали по интернет цене, иначе продаван называет цену, какая придёт в его светлую темноволосую голову. Мы были на экскурсии, где цена варьировалась от 25 до 40 баксов за человека, причём состав и условия экскурсий был одинаковыми. Мы купили несколько поездок: хамам, Демре-Мира-Кекова, бухта Порто Дженевиз, развалины города Перге, теперь по порядку о каждой поездке без прикрас.

Котёнок на дереве

Хамам

Отвозят на маршрутке в общественный хамам. Впервые был в очереди в бане, в целом хамам — это хорошо и обязательно к посещению а начале отпуска, только не этот конкретно, лучше бы взяли хамам в соседнем отеле. На обратном пути водитель пытался нас пересадить в другую маршрутку, но там не хватило сидячих мест, так что удалось отбиться с небольшим скандалом. Цена двадцать баксов с человека. С нами ехали те, кто взял за 18 баксов и за 25, так что делайте выводы.

Демре Мира Кекова

Посещение трёх городов и церкви Николая Чудотворца, также известного как Санта Клаус.

Оказалось, Санта не живёт с женой на Северном Полюсе, а давно умер, и власти скрывают! Перед покупкой экскурсии вам льют в уши, что вы поплывёте на судне со стеклянным дном обозревать руины древних городов, по факту получаются два грязных окошка, в которые ничего не видно кроме зелёной воды. Глумиться про религию не буду (это не одобряют жена и УК РФ), но давно я не видел такого коммерциализированного подхода к религии, особенно в сфере продаж реквизита. Из хорошего — посещение церкви Святого Николая Чудотворца. Монументальное и очень древнее строение. Удивительно, как в начале нашей эры смогли возвести подобное сооружение.

Бухта Порто Дженевиз

Прогулка на кораблике с купанием по трём бухтам: два раза по часу и один на полчаса. Старт корабля из Адрасана. Рекомендую вместо этого купить экскурсию на турецкие Мальдивы — Сулуада. Там вода чище, виды красивее и в целом лучше. Экскурсия запомнилась знакомством с байкерами из Нижнего Новгорода, которые своим ходом через Грузию за шесть дней доехали до Кемера. Из неприятного — тётка в маршрутке, которая заняла чужое место и внезапно забыла русский язык. Так мы и познакомились с байкерами.

Отдельно хочу отметить Адрасан — уникальное место, где кораблики припаркованы кормой прямо к пляжу, вереница кораблей километра два длиной. Вид грандиозный. Если там не были, обязательно побывайте.

Перге

Четыре события по цене одного и пятое в подарок. Сначала везут в парк к верхнему Дюденскому водопаду. Потом часик гуляем по развалинам древнего города Перге. Потом — ужин вкуснейшими котлетками-кюфте, много-много пахлавы, турецкий чаёк. Далее отвозят в «Land of legends» с шоу фонтанов, красивым замком Nickelodeon и элитными магазинами. В завершение программы — вишенка на торте: пересадка посреди ночи из комфортного автобуса в ссаную маршрутку с двумя неизвестными турками, потому что водителю лениво далеко ехать, зато бакшиш брать не лениво.

Замок Nickelodeon

Кемер

Три года назад мы были в Кемере и решили его посетить самостоятельно. Ездили в самую жару на автобусе номер 8, если правильно помню. Вспомнили, что там очень неудобный заход в море через гальку и на пляже не очень-то полежишь. Так что мы были в Кемере один раз. Рядом, кстати, располагается античный ликийский город Фаселис, но туда мы не добрались.

Статуя коня в Кемере

В целом это небольшое путешествие очень понравилось и оставило самые приятные воспоминания — когда ещё понежишься на солнце, когда дома 16 градусов «тепла» и дождь. Это был не очень логичный поступок, когда мы с женой одновременно безработные, но считаю все было не зря, зимой будет что вспомнить.

Небольшая новость

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

Когда я задумался о таком, оказалось, что мой pet-проект — это собственно сайт blog2k.ru, для которого я написал свою тему для WordPress и поддерживаю собственный WordPress плагин со всякими полезными плюшками.

Буквально сегодня выложил в открытый доступ на github исходники своих наработок:

  • тема для WordPress этого сайта: b2k-theme
  • плагин с полезным функционалом: b2k-tools
  • виджет, который при добавлении в область title sidebar, показывает список постов c текущей категорией или тегом: wp-index-widget
  • плагин для виджета отображения погоды: yowindow-widget

Работу плагина wp-index-widget можно увидеть, например, здесь.

Всё выложено под лицензией MIT, можно модифицировать, изменять, брать любую часть и даже использовать в коммерческих целях.

Коммиты и форки всячески приветствуются и не осуждаются. Пул реквесты также, возможно, будут приняты. Enjoy!

Блог Евгения Жирнова