<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Посты on Мини-блог об IT, Linux, Open Source, Tech</title><link>https://coyotle.ru/posts/</link><description>Recent content in Посты on Мини-блог об IT, Linux, Open Source, Tech</description><generator>Hugo -- 0.155.2</generator><language>ru-RU</language><lastBuildDate>Sun, 08 Feb 2026 01:43:13 +0300</lastBuildDate><atom:link href="https://coyotle.ru/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>Как я скучаю по FTP, пока мой CI/CD-пайплайн собирает этот пост</title><link>https://coyotle.ru/posts/it-nostalgia/</link><pubDate>Sun, 08 Feb 2026 01:43:13 +0300</pubDate><guid>https://coyotle.ru/posts/it-nostalgia/</guid><description>&lt;p&gt;На меня периодически накатывает тоска по временам IRC, ICQ (свой номер до сих пор помню), LiveJournal, диалап-модемов, Netscape Navigator-у, Mandrake Linux, настройке modeline в XFree86 для ЭЛТ-монитора, первым PHP-скриптам под Apache и компиляции собственного ядра в CRUX.&lt;br&gt;
Тогда АйТи и вообще интернет были какими-то более живыми. Ввёл запрос в AltaVista — получил страницы синих ссылок, без рекламы товаров, без &amp;ldquo;люди также спрашивают&amp;rdquo;, просто результаты. Подписался в ЖЖ на человека — и магия! читаешь его посты, а не поток мусора от рекомендательных алгоритмов, которые &amp;ldquo;подобрали это специально для тебя&amp;rdquo;.
&lt;img loading="lazy" src="https://coyotle.ru/posts/it-nostalgia/thankyou.png"&gt;&lt;/p&gt;</description></item><item><title>Отвалился XRay/VLESS</title><link>https://coyotle.ru/posts/vless-blocked/</link><pubDate>Sat, 29 Nov 2025 12:23:25 +0300</pubDate><guid>https://coyotle.ru/posts/vless-blocked/</guid><description>&lt;p&gt;Все заинтересованные наверное уже знают, что ТСПУ как-то начал детектить и блокировать VLESS. Изначально я думал что-то случилось с моим сервером, потому что vpn работал через раз, а не отвалился полностью. Потом нашлось обсуждение в &lt;a href="https://github.com/XTLS/Xray-core/issues/5332"&gt;issue xray-core&lt;/a&gt; и статья на хабре.&lt;/p&gt;
&lt;p&gt;Что предлагают для решения проблемы:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;смена транспорта на xHTTP&lt;/li&gt;
&lt;li&gt;поэксперементировать с fingerprint = randomized (или random) &lt;a href="https://xtls.github.io/en/config/transport.html#streamsettingsobject"&gt;https://xtls.github.io/en/config/transport.html#streamsettingsobject&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;поменять порт сервера с 443 на что-то другое&lt;/li&gt;
&lt;li&gt;удалить SNI&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Мне помогло просто поменять &lt;code&gt;fingerprint&lt;/code&gt; с chrome на firefox и очистить &lt;code&gt;serverName&lt;/code&gt;:&lt;/p&gt;</description></item><item><title>Есть ли смысл в CachyOS и прочих клонах Arch Linux?</title><link>https://coyotle.ru/posts/arch-clones/</link><pubDate>Fri, 28 Nov 2025 14:00:13 +0300</pubDate><guid>https://coyotle.ru/posts/arch-clones/</guid><description>&lt;p&gt;От скуки прикрутил к своему Arch репозитории от CachyOS, установил ядро, обновил пакеты и получил обновленную систему. Разработчики заявляют, что их оптимизации дают около 10% прироста производительности. Субъективно я никакого увеличения скорости или отзывчивости не заметил. Единственное, что бросилось в глаза — сломались глобальные шорткаты в Gnome. Не знаю, совпадение это или нет.&lt;/p&gt;
&lt;p&gt;Потом решил поискать в сети объективные цифры и тесты. Нашел несколько видео, где сравнивают производительность в современных играх, и результат оказался&amp;hellip; нулевым. Разница составила плюс-минус 1 FPS по сравнению с ванильным Arch! ОДИН фпс, Карл!&lt;/p&gt;</description></item><item><title>Погружение в 90е (SDXL версия)</title><link>https://coyotle.ru/posts/90s-xl-lora/</link><pubDate>Mon, 05 May 2025 10:21:45 +0300</pubDate><guid>https://coyotle.ru/posts/90s-xl-lora/</guid><description>&lt;p&gt;Натренировал новую SDXL версию своей лоры под стиль аналоговых фото 90-х. LoRa добавляет тени от вспышки, утечки света, цвета в стиле ломо.&lt;/p&gt;
&lt;p&gt;Для SDXL версии пришлось пересобрать датасет, исправить описания и неделю поэксперементировать с параметрами.&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://coyotle.ru/posts/90s-xl-lora/lora_xl.png"&gt;&lt;/p&gt;
&lt;p&gt;Скачать для экспериментов можно на &lt;a href="https://huggingface.co/coyotle/90s_flash_photo"&gt;HuggingFace&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Как обучить языковую модель самостоятельно</title><link>https://coyotle.ru/posts/tarot-bot-p1/</link><pubDate>Sun, 23 Mar 2025 23:37:24 +0300</pubDate><guid>https://coyotle.ru/posts/tarot-bot-p1/</guid><description>&lt;p&gt;Мне не давал покоя вопрос, можно ли на моей нищенской RTX3060 12Gb натренировать свою (не)большую языковую модель. И как оказалось - да, это сделать можно используя Low-Rank Adaptation (LoRA). Т.к. VRAM немного, 8B - это самая большая модель из семейства лама которую можно натренировать на этой карте. Что для этого надо?&lt;/p&gt;
&lt;h2 id="1-грабим-данные"&gt;1. Грабим данные&lt;/h2&gt;
&lt;p&gt;У меня была идея сделать модель которая будет помогать с трактовкой карт Таро, поэтому идем и грабим &lt;del&gt;корованы&lt;/del&gt; сайты с описанием карт и раскладов таро. Для ограбления я написал небольшой python скрипт и с использованием beautifulsoup4 сохранил результат в отдельные JSON файлы.&lt;/p&gt;</description></item><item><title>Mesh-сеть Yggdrasil через TLS за Nginx</title><link>https://coyotle.ru/posts/yggdrasil-over-tls/</link><pubDate>Mon, 24 Feb 2025 22:05:32 +0300</pubDate><guid>https://coyotle.ru/posts/yggdrasil-over-tls/</guid><description>&lt;p&gt;Заметка о том как создать mesh-сеть Yggdrasil over TLS и убрать публичный пир за Nginx. Кратко, что такое Yggdrasil? Это протокол для создания зашифрованной overlay IPv6 mesh сети поверх локальных и публичных сетей. Нам не надо знать как маршрутизируется трафик, через что подключены узлы сети (wi-fi, ethernet, bluetooth), достаточно чтобы пиры как-то могли подключиться друг к другу.&lt;/p&gt;
&lt;p&gt;Зачем использовать TLS и 443 порт? Это будет примитивная маскировка под обычный TLS трафик с указанием в SNI-заголовке левого домена. Этого должно хватить для обхода простых блокировок.&lt;/p&gt;</description></item><item><title>Rust и хейт-войны</title><link>https://coyotle.ru/posts/rust-hate-war/</link><pubDate>Wed, 19 Feb 2025 21:47:03 +0300</pubDate><guid>https://coyotle.ru/posts/rust-hate-war/</guid><description>&lt;p&gt;Довольно часто вижу баталии на форумах вокруг Rust, и тут снова масла в огонь подлила &lt;a href="https://www.opennet.ru/opennews/art.shtml?num=62717"&gt;история с Linux ядром и разработчиком Asahi Linux&lt;/a&gt;. Коммьюнити Rust часто обвиняют в токсичности, но по моим наблюдениям, нападают в основном именно на Rust: сложный синтаксис, много скобочек, зачем вы переписали &lt;em&gt;X&lt;/em&gt; на Rust и т.д. Чтобы не быть жертвой эмоций и реально понять насколько обоснованы претензии к Rust, я потратил около месяца на &lt;a href="https://doc.rust-lang.ru/book/title-page.html"&gt;учебник по Rust&lt;/a&gt; от Стива Клабника и Кэрол Николс.&lt;/p&gt;</description></item><item><title>Эмулируем CHIP-8 на Rust. Часть 2</title><link>https://coyotle.ru/posts/chip-8-part2/</link><pubDate>Sat, 15 Feb 2025 18:40:03 +0300</pubDate><guid>https://coyotle.ru/posts/chip-8-part2/</guid><description>&lt;p&gt;Это продолжение &lt;a href="https://coyotle.ru/posts/chip-8-part1/"&gt;предыдущего поста&lt;/a&gt;, где я начал писать эмулятор CHIP-8 на Rust и вот, в неравной борьбе со своей невнимательностью и опечатками, я его доделал до рабочего состояния.&lt;/p&gt;
&lt;p&gt;Никогда раньше (со времен универа) не занимался ничем низкоуровневым, где понадобились бы битовые сдвиги, маски и вот это всё, но по факту это просто.&lt;/p&gt;
&lt;p&gt;В предыдущей заметке показал как разбирать код ROM-ов на опкоды и интерпретировать их. Далее просто необходимо внимательно реализовать все 35 команд CHIP-8.&lt;/p&gt;</description></item><item><title>Проксируй меня полностью</title><link>https://coyotle.ru/posts/smotrim-rss-proxy/</link><pubDate>Fri, 14 Feb 2025 23:06:04 +0300</pubDate><guid>https://coyotle.ru/posts/smotrim-rss-proxy/</guid><description>&lt;p&gt;Читаю &lt;a href="https://doc.rust-lang.ru/book/title-page.html"&gt;учебник по Rust&lt;/a&gt;, по ходу делаю всякие свистоперделки и вот написал еще один мини проект - прокси сервер для платформы smotrim.ru, который на лету преобразует их JSON-ы в RSS/XML формат. У меня уже был написал небольшой &lt;a href="https://github.com/coyotle/smotrim-rss"&gt;парсер на python&lt;/a&gt; и настроен github-actions для обновления списка лент по крону, и теперь их стало двое.&lt;/p&gt;
&lt;p&gt;Из отличий со скриптом на python, приложение работает в режиме сервера, а не дергается по расписанию, (почти) на каждый запрос генерируется новый XML.&lt;/p&gt;</description></item><item><title>Эмулируем CHIP-8 на Rust. Часть 1</title><link>https://coyotle.ru/posts/chip-8-part1/</link><pubDate>Mon, 10 Feb 2025 22:45:03 +0300</pubDate><guid>https://coyotle.ru/posts/chip-8-part1/</guid><description>&lt;p&gt;А почему бы не замутить эмулятор CHIP-8 на Rust? Эта мысль пришла мне в 2 часа ночи, когда я собирался ложиться спать. К этому моменту я прочитал где-то 15 глав учебника по Rust и написал десяток hello world. &amp;ldquo;Этого должно хватить&amp;rdquo; - подумал я, заварил чай, включил ПК и начал гуглить про архитектуру CHIP-8.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;CHIP-8 - интерпретируемый язык программирования, разработанный Джозефом Вайсбекером для своего микропроцессора 1802. Первоначально он использовался в COSMAC VIP и Telmac 1800 - 8-битных микрокомпьютерах, выпущенных в середине 1970-х.
CHIP-8 был разработан для того, чтобы его было легко программировать, а также для того, чтобы он использовал меньше памяти, чем другие языки программирования, такие как BASIC.&lt;/p&gt;</description></item><item><title>Миграция с wireguard на amneziawg</title><link>https://coyotle.ru/posts/amnezia/</link><pubDate>Fri, 15 Nov 2024 10:12:04 +0300</pubDate><guid>https://coyotle.ru/posts/amnezia/</guid><description>&lt;p&gt;После каких-то очередных манипуляций на Ростелекоме мой wireguarg туннель приказал долго жить (как и IPv6 почему-то), поэтому перехожу на amneziawg. Amneziawg - это форк wg поддерживающий добавление шума в стандартный протокол wireguard.&lt;/p&gt;
&lt;p&gt;Понятно, что в час Х, когда государство решит закрутить гайки, этот протокол будет легко забанен, но пока он работает и можно пользоваться.
На крайний случай останется wg через vless, хотя скорость в таком случае не очень.&lt;/p&gt;
&lt;h2 id="установка-в-ubuntu"&gt;Установка в Ubuntu&lt;/h2&gt;
&lt;p&gt;Включаем источники src пакетов (deb-src) в &lt;code&gt;/etc/apt/sources.list.d/ubuntu.sources&lt;/code&gt;&lt;/p&gt;</description></item><item><title>Shell доступ к хосту через LLM и мини-игра</title><link>https://coyotle.ru/posts/llm-shell/</link><pubDate>Fri, 09 Aug 2024 23:10:56 +0300</pubDate><guid>https://coyotle.ru/posts/llm-shell/</guid><description>&lt;p&gt;Разбираясь с &lt;a href="https://ollama.com/"&gt;ollama&lt;/a&gt; и моделью &lt;a href="https://ollama.com/library/llama3.1"&gt;llama3.1&lt;/a&gt; увидел в документации, что ollama для некоторых моделей поддерживает вызов функций. Если коротко - модели под капотом передается JSON описывающий набор функций доступных ей для выполнения. Так можно добавить модели функцию получения информации из внешних источников или взаимодействия с какими-то системами. В документации приводят функцию получения текущей погоды для указанного города:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;function&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;function&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;get_current_weather&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Get the current weather for a city&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;parameters&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;object&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;properties&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;city&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;The name of the city&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;required&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;city&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Простой код для использования функции будет примерно таким:&lt;/p&gt;</description></item><item><title>Как запустить Flux с помощью ComfyUI на 12ГБ VRAM</title><link>https://coyotle.ru/posts/flux-setup/</link><pubDate>Mon, 05 Aug 2024 00:45:04 +0300</pubDate><guid>https://coyotle.ru/posts/flux-setup/</guid><description>&lt;p&gt;В инфополе ворвалась новая диффузионная модель Flux и порвала всех конкурентов.
Из своих тестов и того, что видел на Reddit, изображения значительно лучше, особенно в плане анатомии и злосчастных рук, чем то, что делает Stable Diffusion.
Модель доступна в двух вариантах Schnell (разрешено использование в коммерческих проектах) и Dev (не для коммерческого использования). Обе версии имеют один размер, но Schnell генерирует изображения за меньшее число шагов и немного худшего качества чем Dev.
Модели значительно больше по размеру чем SDXL и новая (неудачная) SD3, и весят почти 24ГБ.&lt;/p&gt;</description></item><item><title>Синхронизация Obsidian [upd]</title><link>https://coyotle.ru/posts/obsidian-live-sync-upd/</link><pubDate>Sun, 21 Jul 2024 23:10:56 +0300</pubDate><guid>https://coyotle.ru/posts/obsidian-live-sync-upd/</guid><description>&lt;p&gt;Это новая версия &lt;a href="https://coyotle.ru/posts/obsidian-live-sync/"&gt;предыдущей заметки&lt;/a&gt; про синхронизацию Obsidian с помощью плагина LiveSync т.к. плагин обновился, плюс более подробно опишу настройку CouchDB.&lt;/p&gt;
&lt;h2 id="установка-и-настройка-couchdb"&gt;Установка и настройка CouchDB&lt;/h2&gt;
&lt;p&gt;Запускать базу будем в docker. Создаем директории для хранения:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mdkir -p ~/docker/couchdb/data
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/docker/couchdb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Создаем &lt;code&gt;docker-compose.yaml&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;3&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;couchserver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;couchdb:3.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;127.0.0.1:5984:5984&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;COUCHDB_USER=admin&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;COUCHDB_PASSWORD=COUCH-ADMIN-PASS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# ваш админский пароль для доступа к серверу&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./data:/opt/couchdb/data&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;always&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Публикуем CouchDB через nginx:&lt;/p&gt;</description></item><item><title>Добавляем ИИ боту распознавание голосовых сообщений</title><link>https://coyotle.ru/posts/simple-ai-bot-with-voice/</link><pubDate>Sat, 08 Jun 2024 13:06:04 +0300</pubDate><guid>https://coyotle.ru/posts/simple-ai-bot-with-voice/</guid><description>&lt;p&gt;В продолжение &lt;a href="https://coyotle.ru/posts/simple-ai-bot/"&gt;предыдущей заметки&lt;/a&gt; давайте сделаем ещё один шаг и добавим возможность боту отвечать текстом на голосовые сообщения.
Для распознования голоса будем использовать python обертку над whisper.cpp.&lt;/p&gt;
&lt;p&gt;Более подробно как работает бот смотрите предыдущий пост, тут я сделаю небольшой рефакторинг и добавлю новый обработчик для голосовых.&lt;/p&gt;
&lt;p&gt;Устанавливаем зависимости&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;deep-translator==1.11.4
llama_cpp_python==0.2.77
loguru==0.7.2
python-dotenv==1.0.1
requests==2.32.3
telebot==0.0.5
whisper_cpp_python==0.2.0
&lt;/code&gt;&lt;/pre&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;uuid&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;uuid4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;telebot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;deep_translator&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;GoogleTranslator&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;llama_cpp&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Llama&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;loguru&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;telebot.types&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;whisper_cpp_python&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Whisper&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;TG_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;TG_TOKEN&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;telebot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TeleBot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TG_TOKEN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Загружаем llama-3 модель&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Llama&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;model_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./models/llama3/Meta-Llama-3-8B-Instruct-Q4_K_M.gguf&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chat_format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;llama-3&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# n_gpu_layers=-1, # Uncomment to use GPU acceleration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# seed=1337, # Uncomment to set a specific seed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# n_ctx=2048, # Uncomment to increase the context window&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Загружаем whisper.cpp модель&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;whisper_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Whisper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./models/whisper/ggml-base.bin&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Словарь для хранения историй сообщений&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;user_message_history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Стартовое сообщение бота&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@bot.message_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;commands&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;start&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;help&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_welcome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Я ИИ бот на базе llama-3. Можешь отправить мне текстовое или голосовое сообщение.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Вынесем логику работы с историей сообщений и llama моделью в отдельную функцию&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_chat_completion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Получаем историю сообщений текущего пользователя&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;user_history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user_message_history&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;user_history&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;role&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;user&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Добавим в контекст текущую дату и время&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;current_date_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s2"&gt; %B %Y, %H:%M MSK&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;role&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Ты полезный ИИ помощник.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Текущая дата: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;current_date_time&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;user_history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_chat_completion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;reply&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;choices&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;assistant: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Добавляем ответ бота в историю текущего пользователя&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;user_history&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;role&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;assistant&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;user_message_history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user_history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Обработчик текстовых сообщений&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@bot.message_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;message_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chat_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;user &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_chat_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chat_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;typing&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;reply&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create_chat_completion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Отправляем ответ пользователю&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chat_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Добавляем обработчик голосовых сообщений&lt;/p&gt;</description></item><item><title>Простой llama-3 телеграм бот</title><link>https://coyotle.ru/posts/simple-ai-bot/</link><pubDate>Wed, 01 May 2024 15:06:04 +0300</pubDate><guid>https://coyotle.ru/posts/simple-ai-bot/</guid><description>&lt;p&gt;В заметке расскажу как на python сделать простого чат бота для телеграм на базе последней версии llm модели llama-3.&lt;/p&gt;
&lt;p&gt;Предположим у нас уже установлен python и CUDA (если хотите использовать gpu для ускорения).
Для взаимодействия с моделью на python есть несколько вариантов, чтобы не усложнять будем использовать библиотеку llama.cpp и квантованную модель в формате GGUF. Обратите внимание, нужна Instruct версия.&lt;/p&gt;
&lt;h2 id="подготовка"&gt;Подготовка&lt;/h2&gt;
&lt;p&gt;В телеграм с помощью &lt;code&gt;@BotFather&lt;/code&gt; создайте нового бота и получите токен.&lt;/p&gt;</description></item><item><title>Forgejo Actions в Podman и Quadlet</title><link>https://coyotle.ru/posts/podman-runner/</link><pubDate>Fri, 05 Apr 2024 22:48:54 +0300</pubDate><guid>https://coyotle.ru/posts/podman-runner/</guid><description>&lt;p&gt;Только обнаружил, что уже год Forgejo поддерживает экшены на подобии Github Actions для автоматического запуска ci/cd пайплайнов.
Пайплайны по синтаксису совместимы с Github и поддерживают готовые Github экшены &lt;a href="https://github.com/marketplace?type=actions"&gt;https://github.com/marketplace?type=actions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;У меня изначально ci/cd был реализован на Forgejo + Drone, потом Drone был заменен на Woodpecker (форк Drone),
ну а затем собственно увидел, что появился встроенный механизм и перешел на него.&lt;/p&gt;
&lt;p&gt;Для работы экшен модуль должен быть включен в конфиге Forgejo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[actions]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ENABLED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;DEFAULT_ACTIONS_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;github&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ZOMBIE_TASK_TIMEOUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;10m&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ENDLESS_TASK_TIMEOUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;3h&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ABANDONED_JOB_TIMEOUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;24h&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;SKIP_WORKFLOW_STRINGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;[skip ci],[ci skip],[no ci],[skip actions],[actions skip]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Так же как в Github за работу экшен отвечают ранеры, которые могут быть запущены как обычные приложения, либо в Docker-контейнере.
&lt;img loading="lazy" src="https://coyotle.ru/posts/podman-runner/runner.webp"&gt;
Во втором случае в контейнер монтируют docker.sock хоста для запуска ранером контейнеров с задачами.
Всё это прекрасно работало пока не решил отказаться от Docker и перейти на Podman.&lt;/p&gt;</description></item><item><title>Проброс портов через Xray реверс-прокси</title><link>https://coyotle.ru/posts/xray-proxy/</link><pubDate>Thu, 04 Jan 2024 19:10:04 +0300</pubDate><guid>https://coyotle.ru/posts/xray-proxy/</guid><description>&lt;p&gt;В заметке опишу как организовать доступ к серверу в локальной сети через Xray. Про базовую настройку Xray можно посмотреть &lt;a href="https://coyotle.ru/posts/xray-and-nginx/"&gt;тут&lt;/a&gt;.
&lt;img alt="Схема" loading="lazy" src="https://coyotle.ru/posts/xray-proxy/proxy.png"&gt;&lt;/p&gt;
&lt;p&gt;В терминологии xray схема с реверс-прокси состоит из двух участников: &lt;code&gt;portal&lt;/code&gt; и &lt;code&gt;bridge&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Portal - это сервер который доступен из интернет и который выполняет роль реверс-прокси.&lt;/li&gt;
&lt;li&gt;Bridge - сервер/клиент который находится в приватной сети и через который осуществляется доступ к ресурсу в приватной сети.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Допустим у нас в локальной сети есть веб-сервер без публичного IP и мы хотим опубликовать его через xray portal.
Клиенты из интернет будут подключаться к публичному серверу А и через служебный канал (vless, shadowsocks&amp;hellip;) между A и B получать доступ к приватному серверу.&lt;/p&gt;</description></item><item><title>Грабим корованы с Youtube в Telegram</title><link>https://coyotle.ru/posts/rob-caravans-youtube-to-telegram/</link><pubDate>Fri, 08 Dec 2023 17:21:45 +0300</pubDate><guid>https://coyotle.ru/posts/rob-caravans-youtube-to-telegram/</guid><description>&lt;p&gt;Написал небольшой скрипт для разграбления Youtube канала iXBT.Games и отправки аудио в телеграм. Если следишь за творчеством ребят и хочешь слушать видео и стримы в виде подкастов в телеге - подключайся &lt;a href="https://t.me/ixbt_audio"&gt;https://t.me/ixbt_audio&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Наверное нет смысла заводить репу на github для одного скрипта, выложу тут как есть, может кому-то пригодится.&lt;/p&gt;
&lt;p&gt;В каталоге со скриптом необходимо создать каталог &lt;code&gt;cache/&lt;/code&gt;, &lt;code&gt;thumb.jpg&lt;/code&gt; - изображение 320x320 для обложки к аудио и &lt;code&gt;.env&lt;/code&gt; файл с переменными:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-env" data-lang="env"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ID канала&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;YOUTUBE_CHANNEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;UC4e_XPBiiIO4fo4_CucxQeg
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Обрабатывать только одно видео за раз&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;PROCESS_ONE_VIDEO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Токен телеграм-бота. Получить у @BotFather&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;TG_BOT_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ID канала или пользователя куда отправлять сообщения&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;TG_CHAT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Использовать локальный telegram bot api сервер&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# для отправки файлов &amp;gt; 50MB&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# https://github.com/tdlib/telegram-bot-api/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;TG_LOCAL_MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;TG_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:8081/bot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;TG_BASE_FILE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:8081/file/bot
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Собственно код скрипта:&lt;/p&gt;</description></item><item><title>Погружение в 90е</title><link>https://coyotle.ru/posts/90s-v2-lora/</link><pubDate>Sun, 05 Nov 2023 17:21:45 +0300</pubDate><guid>https://coyotle.ru/posts/90s-v2-lora/</guid><description>&lt;p&gt;Для ностальгирующих по эстетике 90х.
После пары недель экспериментов с kohya_ss и подробом параметров зарелизил вторую версию LoRa для создания картинок в стиле фотографий на мыльницы со вспышкой.
Скачать для экспериментов можно на &lt;a href="https://civitai.com/models/84662"&gt;Civitai&lt;/a&gt;.
&lt;img loading="lazy" src="https://coyotle.ru/posts/90s-v2-lora/90s_v2.png"&gt;
По сравнению с первой версией эту лору можно использовать с большей strength не ломая изображение.
В последний заход потратил часов восемь на тренировку и около 80 эпох. По факту оказалось, что после 5-6 эпох LoRa уже сильно перетренирована, хотя Loss так и не достиг минимума и продолжал уменьшаться.&lt;/p&gt;</description></item><item><title>Controlnet для тг-бота pixelmuse</title><link>https://coyotle.ru/posts/pixelmuse-controlnet/</link><pubDate>Tue, 17 Oct 2023 20:21:45 +0300</pubDate><guid>https://coyotle.ru/posts/pixelmuse-controlnet/</guid><description>&lt;p&gt;Добавил новую функцию для telegram-бота &lt;a href="https://t.me/pixelmuse_bot"&gt;@pixelmuse_bot&lt;/a&gt;. Теперь на вход ему можно отправить кривой рисунок с командой в описании &lt;code&gt;/imagine2 текст запроса&lt;/code&gt; и на выходе получить что-то осмысленное и даже красивое.&lt;/p&gt;
&lt;p&gt;Как это работает под капотом. Никакой магии, для управления нейросетью используем &lt;a href="https://huggingface.co/docs/diffusers/main/en/api/pipelines/controlnet_sdxl"&gt;controlnet&lt;/a&gt;. Controlnet заставляет нейросеть использовать информацию о границах объектов как опору для создания нового изображения.&lt;/p&gt;
&lt;p&gt;После получения изображения от пользователя обрабатываем его с помощью cv2.Canny для определения краев. Тут пришлось поэксперементировать с параметрами чтобы края определялись в том числе на фотографиях, где переходы, например на лице, могут быть плавными, а потеря этих границ даёт модели слишком много свободы для творчества.&lt;/p&gt;</description></item><item><title>Telegram-бот для создания изображений нейросетью</title><link>https://coyotle.ru/posts/pixel-muse/</link><pubDate>Fri, 22 Sep 2023 17:21:45 +0300</pubDate><guid>https://coyotle.ru/posts/pixel-muse/</guid><description>&lt;p&gt;В общем, кому не хватало Midjourney у нас дома - добро пожаловать в &lt;a href="https://t.me/pixelmuse_bot"&gt;@pixelmuse_bot&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Что бот умеет на данный момент:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Создавать картинки по текстовому запросу&lt;/li&gt;
&lt;li&gt;Используется автоматический машинный перевод текста на английский, поэтому запрос может быть практически на любом языке&lt;/li&gt;
&lt;li&gt;Можно выбрать из 5 моделей: реализм, аниме, киборги, sci-fi окружение, стикеры (по факту под капотом две модели + разные LoRa)&lt;/li&gt;
&lt;li&gt;Можно загрузить свою фотографию для обработки img2img&lt;/li&gt;
&lt;li&gt;Можно сделать апскейл результата x1.5. Для апскейла используется нейронка Real-ESRGAN&lt;/li&gt;
&lt;li&gt;Даю 20 токенов для тестов (20 изображений) с лимитом 10 токенов в день&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="dev-лог"&gt;Dev-лог&lt;/h2&gt;
&lt;p&gt;Какое-то время ковырял Stable Diffusion в Автоматик111 и ComfyUI. В один &lt;del&gt;прекрасный&lt;/del&gt; депрессивный день решил посмотреть, как работать с сетью напрямую в python. Сделать это можно с помощью библиотеке diffusers от Hugging Face. Написал пятистрочный скрипт и подумал почему бы ради прикола не приделать к нему телеграм бота, и тут понеслось.&lt;/p&gt;</description></item><item><title>Cyberpunk 2023</title><link>https://coyotle.ru/posts/cyberpunk-2023/</link><pubDate>Thu, 07 Sep 2023 07:12:04 +0300</pubDate><guid>https://coyotle.ru/posts/cyberpunk-2023/</guid><description>&lt;p&gt;С другой стороны, а кто из IT-специалистов не мечтал пожить в каберпанк антиутопии?
Минцифры опубликовало проект изменений в постановление Правительства РФ от 26 октября 2012 г. № 1101, согласно которым РКН наделяется правом включать в реестр интернет-ресурсов, доступ к которым в России должен блокироваться, сайты с информацией о способах, методах обеспечения доступа к информационным ресурсам и информационно-телекоммуникационным сетям, доступ к которым ограничен на территории РФ. Источники СМИ сообщили, что новый проект постановления Минцифры коснётся сайтов со списками VPN или инструкциями по созданию собственных VPN и прокси-серверов, позволяющих обходить ограничения по запрету.&lt;/p&gt;</description></item><item><title>Xray с XTLS-Reality и Nginx на одном порту</title><link>https://coyotle.ru/posts/xray-and-nginx/</link><pubDate>Sun, 13 Aug 2023 18:12:04 +0300</pubDate><guid>https://coyotle.ru/posts/xray-and-nginx/</guid><description>&lt;p&gt;Что делаем? Настроим так чтобы на одном порту &lt;code&gt;443&lt;/code&gt; висел и nginx с нашими сайтами и xray XTLS-Reality, который работает как прокси для авторизованных пользователей и притворяется валидным сайтом (в примере &lt;a href="https://www.google.com"&gt;www.google.com&lt;/a&gt;) для всех остальных.&lt;/p&gt;
&lt;p&gt;XTLS-Reality предназначен для защиты от выявления методом active probing. В отличие от старых протоколов (Shadowsocks, VMess, VLESS, и транспорта XTLS-Vision), определение “свой/чужой” здесь происходит на этапе TLS-хендшейка в момент чтения ClientHello. Если клиент опознан как “свой”, сервер работает как прокси, а если нет - TLS подключение передается на другой хост с TLS (например, google.com), и таким образом клиент (или цензор, желающий методом active probing проверить, что прячется на том конце) получит настоящий TLS-сертификат от google.com и настоящие данные с этого сервера.&lt;/p&gt;</description></item><item><title>У нас есть ChatGPT дома</title><link>https://coyotle.ru/posts/chatgpt-at-home/</link><pubDate>Thu, 27 Apr 2023 09:45:03 +0300</pubDate><guid>https://coyotle.ru/posts/chatgpt-at-home/</guid><description>&lt;p&gt;В статье опишу настройку web API и web-чат похожего на ChatGPT для LLaMA-подобных моделей. Всё это довольно сносно работает на CPU Ryzen 3600 + 32ГБ ОЗУ.&lt;/p&gt;
&lt;h2 id="api--веб-чат"&gt;API + веб чат&lt;/h2&gt;
&lt;p&gt;Для настройки нам понадобятся три проекта:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;llama.cpp&lt;/strong&gt; - мозг нашей системы&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;gpt-llama.cpp&lt;/strong&gt; - эмулирует API от OpenAI. Реализовано не всё&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;chatbot-ui&lt;/strong&gt; - web интерфейс для доступа к моделям OpenAI&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;После установки компонентов должна получиться такая структура:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;local-chat - корень проекта
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── chatbot-ui
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── gpt-llama.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── llama.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    ├── main*
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    └── models/your-ggml-model.bin
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="llamacpp"&gt;llama.cpp&lt;/h3&gt;
&lt;p&gt;Думаю многие уже попробовали установить и пообщаться с llama-подобными моделями, но в любом случае опишу процесс установки.&lt;/p&gt;</description></item><item><title>Как поговорить с LLaMA голосом</title><link>https://coyotle.ru/posts/talk-to-llama/</link><pubDate>Wed, 26 Apr 2023 00:32:30 +0300</pubDate><guid>https://coyotle.ru/posts/talk-to-llama/</guid><description>&lt;p&gt;Наверное уже все пообщались в текстовом режиме с llama-подобными моделями, в этой заметке расскажу как можно настроить полностью голосовое общение с моделью.&lt;/p&gt;
&lt;p&gt;Для общения нам понадобятся:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;whisper.cpp&lt;/strong&gt; - преобразование голоса в текст&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;silero&lt;/strong&gt; - синтез речи&lt;/li&gt;
&lt;li&gt;модель совместимая с &lt;strong&gt;llama.cpp&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="silero-tts"&gt;Silero TTS&lt;/h3&gt;
&lt;p&gt;По моему Silero лучший синтезатор речи который можно запустить под Linux с довольно приличной скорость на CPU. На хабре есть несколько статей от разработчиков, поищите, интересное чтиво.
Пользователи Mac могу пропустить этот шаг и использовать для синтеза Siri.&lt;/p&gt;</description></item><item><title>Этика ИИ. Корпорации врут, а мы катимся в пропасть?</title><link>https://coyotle.ru/posts/ai-and-ethic/</link><pubDate>Thu, 23 Mar 2023 12:04:35 +0300</pubDate><guid>https://coyotle.ru/posts/ai-and-ethic/</guid><description>&lt;p&gt;Если попытаться спросить ChatGPT о чем-то связанном с насилием, криминалом и т.п. - он ответит, что не будет обсуждать эту тему т.к. это не этично. OpenAI и Microsoft постоянно рассказывают о своих усилиях в области безопасности ИИ. Тот же Google какое-то время назад прикрыл доступ к своей языковой модели после того как пользователи научили её &amp;ldquo;плохим&amp;rdquo; вещам. Но так ли всё хорошо с безопасным и этичным использованием ИИ и куда мы идем?&lt;/p&gt;</description></item><item><title>Подготовка данных для нейронной сети</title><link>https://coyotle.ru/posts/ml-preparing-data/</link><pubDate>Sat, 11 Feb 2023 23:34:29 +0300</pubDate><guid>https://coyotle.ru/posts/ml-preparing-data/</guid><description>&lt;p&gt;На волне шумихи вокруг GPT-3 появилось желание покапаться во внутреннем устройстве нейронных сетей и попробовать написать сеть для классификации текстов по категориям/тэгам. Это первая заметка из серии, речь в ней пойдет о предварительной подготовке данных.&lt;/p&gt;
&lt;p&gt;Зачем необходима подготовка данных? Текстовые данные не могут быть использованы напрямую в моделях машинного обучения, так как в нейронах используются простые математические функции которые работают с числовыми данными. Для подготовки текстовых данных используют так называемое кодирование слов - это преобразование текстовых данных в числовые (векторные) представления, которые затем можно использовать для машинного обучения.
&lt;img loading="lazy" src="https://coyotle.ru/posts/ml-preparing-data/leo_and_ml.png"&gt;
Существует много способов кодирования, вот некоторые из них:&lt;/p&gt;</description></item><item><title>Живая синхронизация заметок Obsidian</title><link>https://coyotle.ru/posts/obsidian-live-sync/</link><pubDate>Sat, 04 Feb 2023 10:06:01 +0300</pubDate><guid>https://coyotle.ru/posts/obsidian-live-sync/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Доступна &lt;a href="https://coyotle.ru/posts/obsidian-live-sync-upd/"&gt;обновленная инструкция&lt;/a&gt; по настройке плагина и CouchDB&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Для тех кто не в курсе, &lt;a href="https://obsidian.md/"&gt;Obsidian&lt;/a&gt; - кроссплатформенная программа для ведения заметок в markdown формате, которую можно использовать для создания личной базы знаний или вашего «второго мозга» по методу Zettelkasten. Как работает метод можно почитать по &lt;a href="https://habr.com/ru/post/508672/"&gt;ссылке&lt;/a&gt;. На самом деле Obsidian не обязательно использовать именно как «второй мозг», это просто удобная программа для ведения заметок с большим количеством плагинов.&lt;/p&gt;
&lt;p&gt;Один минус - Obsidian из коробки поддерживает синхронизацию заметок только через собственный платный сервис. Из плюсов - вся база хранится в виде обычных md файлов которые можно синхронизировать между устройствами через облачные сервисы. У меня изначально синхронизировалось через NextCloud, но в мобильном клиенте NC постоянно возникают конфликты, которые надо разрешать руками. Вообще мобильный клиент да и сам nextcoud бесят, может кто-то знает альтернативы?&lt;/p&gt;</description></item><item><title>Автоматизация сборки и публикации блога Hugo</title><link>https://coyotle.ru/posts/deploy-hugo-blog/</link><pubDate>Thu, 02 Feb 2023 11:52:31 +0300</pubDate><guid>https://coyotle.ru/posts/deploy-hugo-blog/</guid><description>&lt;p&gt;В предыдущей заметке мы установили &lt;a href="https://coyotle.ru/posts/cicd-at-home/"&gt;Drone CI&lt;/a&gt;, в этой настроим автоматическую сборку и публикацию блога при пуше в git-репозиторий.&lt;/p&gt;
&lt;p&gt;После настройки Drone и авторизации в нем вы должны увидеть доступные вам репозитории. Для того чтобы Drone начал обрабатывать пайплайны необходимо активировать репозиторий. Для это в секции &lt;code&gt;Repositories&lt;/code&gt; заходим в нужный репозиторий и нажамаем &lt;code&gt;Activate repository&lt;/code&gt;. На странице настроек можно отключить вебхуки которые будут отслеживаться, настроить режим приватности, максимальное время выполнения пайплайна и название файла в котором Drone будет искать описание пайплайна (по умолчанию .drone.yml). Нажимаем &lt;code&gt;Save changes&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Drone CI</title><link>https://coyotle.ru/posts/cicd-at-home/</link><pubDate>Fri, 27 Jan 2023 03:48:54 +0300</pubDate><guid>https://coyotle.ru/posts/cicd-at-home/</guid><description>&lt;p&gt;В продолжение заметки &amp;ldquo;&lt;a href="https://coyotle.ru/posts/github-at-home"&gt;У нас есть github дома&lt;/a&gt;&amp;rdquo; добавим к нашему окружению систему автоматического тестирования и доставки ПО &lt;a href="https://www.drone.io/"&gt;Drone CI&lt;/a&gt;.
Документацию можно почитать тут &lt;a href="https://docs.drone.io/"&gt;https://docs.drone.io/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Из плюсов Drone по сравнению с Jenkins: простота установки, настройки и сопровождения, не надо изучать groovy, всё пишется на yaml.&lt;/p&gt;
&lt;p&gt;Drone CI состоит из двух сервисов: собственно Drone и ранеров которые будут выполнять необходимые задачи, в даном случае ранеры используют докер хост системы для запуска задач.&lt;/p&gt;
&lt;p&gt;Сам drone не имеет базы пользователей и использует OAuth внешней системы для авторизации пользователей.
Для настройки OAuth перейдите в раздел &lt;code&gt;user/settings/applications&lt;/code&gt; на вашем экземпляре forgejo/gitea и в подразделе &lt;code&gt;Authorized OAuth2 Applications&lt;/code&gt; создайте новое приложение. В поле Redirect URI укажите адрес вашего drone сервера, например &lt;code&gt;https://drone.example.ru/login&lt;/code&gt;. После создания приложения скопируйте client id и secret, они понадобятся ниже.&lt;/p&gt;</description></item><item><title>Обновление маршрутов</title><link>https://coyotle.ru/posts/update-vpn-routes/</link><pubDate>Mon, 23 Jan 2023 18:12:27 +0300</pubDate><guid>https://coyotle.ru/posts/update-vpn-routes/</guid><description>&lt;p&gt;Надоело вручную обновлять на роутере список маршрутов для блокировки запрещенных сайтов. Я дополнительно блокировал не всё подряд, а буквально несколько сайтов, но всё равно надоело, поэтому написал небольшой скрипт для автоматизации рутины. Интерфейс &lt;code&gt;tun0&lt;/code&gt; терминирует все подключения в &lt;code&gt;/dev/null&lt;/code&gt; если что.&lt;/p&gt;
&lt;p&gt;Скрипт скачивает список адресов которые надо заблокировать с &lt;a href="https://antifilter.download/"&gt;https://antifilter.download/&lt;/a&gt; в файл &lt;code&gt;ipsum_new&lt;/code&gt; и немного фильтрует чтобы избежать подстановок, сравнивает с предыдущей версией списка в &lt;code&gt;ipsum_cur&lt;/code&gt; и помещает разницу в &lt;code&gt;ipsum_diff&lt;/code&gt;.
Затем берём разницу и добавляем или удаляем маршрут в таблице маршрутизации в зависимости от знака + или - в diff-файле.
В конце скрипта замещаем текущий &lt;code&gt;ipsum_cur&lt;/code&gt; новым файлом.&lt;/p&gt;</description></item><item><title>Крайний из нас</title><link>https://coyotle.ru/posts/the-last/</link><pubDate>Thu, 19 Jan 2023 10:41:38 +0300</pubDate><guid>https://coyotle.ru/posts/the-last/</guid><description>&lt;p&gt;&lt;img loading="lazy" src="https://coyotle.ru/posts/the-last/cover.webp"&gt;
Я попытался посмотреть первую серию The Last Of Us. Тут можно поставить точку т.к. предыдущее предложение содержит всю нужную информацию. Меж тем оценки у сериала зашкаливают 9.4 на imdb, 8.7 на кинопоиск. У меня только два вопроса: голливуд действительно стал так ненавидеть красивых женщин или диктат повестки и страх перед культурой отмены довёл до вот этого и второй вопрос, кто все эти люди, которые ставят &lt;del&gt;говну&lt;/del&gt; посредственному кино такие высокие оценки?&lt;/p&gt;</description></item><item><title>Литературные часы</title><link>https://coyotle.ru/posts/literature-clock/</link><pubDate>Wed, 18 Jan 2023 22:08:54 +0300</pubDate><guid>https://coyotle.ru/posts/literature-clock/</guid><description>&lt;p&gt;Мой СДВГ заставил меня несколько дней посвятить написанию небольшого проекта &amp;ldquo;литературные часы&amp;rdquo;, которые показывают время используя цитаты из книг.&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://coyotle.ru/posts/literature-clock/clock.webp"&gt;&lt;/p&gt;
&lt;p&gt;Вдохновился я вот &lt;a href="https://literature-clock.jenevoldsen.com/"&gt;этим&lt;/a&gt; и &lt;a href="https://www.instructables.com/Literary-Clock-Made-From-E-reader/"&gt;этим&lt;/a&gt;.
В англоязычной версии литературные часы основаны на базе цитат которую изначально собрала газета The Guardian. В 2011 году они попросили своих читателей присылать цитаты из книг, в которых упоминается время. Цитаты планировали использовать в постройке инсталляцию для литературного фестиваля. Таким образом, на их веб-сайте есть две версии списка &lt;a href="https://www.theguardian.com/books/table/2011/apr/21/literary-clock?CMP=twt_gu"&gt;1&lt;/a&gt; и &lt;a href="https://www.guardian.co.uk/books/booksblog/2011/apr/15/christian-marclay-the-clock-literature"&gt;2&lt;/a&gt;, объединенный и дополненный список англоязычных цитат можно найти &lt;a href="https://github.com/JohannesNE/literature-clock"&gt;тут&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>У нас есть github дома</title><link>https://coyotle.ru/posts/github-at-home/</link><pubDate>Tue, 10 Jan 2023 10:22:24 +0300</pubDate><guid>https://coyotle.ru/posts/github-at-home/</guid><description>&lt;p&gt;В этой заметке не буду обсуждать вопрос зачем поднимать свой git-сервер, а не использовать github/gitlab/codeberg или даже sourceforge.&lt;/p&gt;
&lt;h2 id="как-развернуть-свой-легкий-git-сервер"&gt;Как развернуть свой легкий git сервер&lt;/h2&gt;
&lt;p&gt;Начнем с того, что самый простой способ - это создать &lt;code&gt;git --bare init&lt;/code&gt; репозиторий на вашем сервере и написать обычные скрипты для выполнения автоматических задач. Собственно этот блог собирался скриптом который запускался в cron, делал git pull репозитория с кодом блога, а потом собирал и публиковал результат.&lt;/p&gt;</description></item><item><title>ИИ, назад в будущее</title><link>https://coyotle.ru/posts/ai-back-to-the-future/</link><pubDate>Fri, 06 Jan 2023 10:00:00 +0300</pubDate><guid>https://coyotle.ru/posts/ai-back-to-the-future/</guid><description>&lt;p&gt;Департамент образования Нью-Йорка запретил доступ к чат-боту ChatGPT в сетях и на устройствах гос школ города. Отдельные школы смогут запросить доступ к ChatGPT если они занимаются изучением ИИ. &amp;ldquo;Инструмент не развивает навыки критического мышления&amp;rdquo; - заявила чиновник отдела образования.&lt;/p&gt;
&lt;p&gt;Также международная конференция по машинному обучению (ICML) запретила учёным представлять статьи, созданные с помощью больших языковых моделей.&lt;/p&gt;
&lt;p&gt;В то же время Microsoft объявила, что до апреля 2023 года запустит версию поисковика Bing с системой ИИ на основе ChatGPT. Microsoft надеется, что это позволит им стать более конкурентой по отношению к поиску Google.
Компания выступает одним из крупнейших инвесторов OpenAI с 2019 года (см. &lt;a href="https://coyotle.ru/posts/brave-new-world"&gt;Новый дивный мир&lt;/a&gt;).&lt;/p&gt;</description></item><item><title>Шорткоды в Hugo</title><link>https://coyotle.ru/posts/shotcodes/</link><pubDate>Fri, 06 Jan 2023 01:21:59 +0300</pubDate><guid>https://coyotle.ru/posts/shotcodes/</guid><description>&lt;p&gt;Шорткоды (shortcodes) - позволяют вставлять в markdown страницы заготовленные html блоки и передавать им параметры. В Hugo уже есть набор готовых шорткодов (см. &lt;a href="https://gohugo.io/content-management/shortcodes/"&gt;документацию&lt;/a&gt;), которые позволяют например вставлять видео youtube или vimeo.&lt;/p&gt;
&lt;p&gt;Следующий шорткод вставит в страницу iframe с youtube с указанными параметрами &lt;code&gt;id&lt;/code&gt; и &lt;code&gt;autoplay&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{{&lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;youtube&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;hzWl_j__KFU&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;autoplay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;false&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/hzWl_j__KFU?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
Параметры бывают позиционными и именованными.&lt;/p&gt;</description></item><item><title>Комментарии для статичного блога</title><link>https://coyotle.ru/posts/comments-for-static-blog/</link><pubDate>Thu, 05 Jan 2023 00:00:00 +0300</pubDate><guid>https://coyotle.ru/posts/comments-for-static-blog/</guid><description>&lt;p&gt;Существует довольно много вариантов добавить систему комментариев на статичный сайт.
Погуглив нашел несколько:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Disqus&lt;/strong&gt; - наверное самая известная и распространенная платформа. Discus я отмел, т.к. не планирую покупать подписку и не хочу заставлять читателей смотреть рекламу.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://github.com/umputun/remark42"&gt;Remark42&lt;/a&gt;&lt;/strong&gt; - opensource платформа для самохостинга. Много возможностей и функций, импорт из Wordpress и Disqus. Возможно это лучший выбор если вы не против администрировать ещё +1 систему, но для моего мини-блога это излишество.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://github.com/utterance/utterances"&gt;Utterances&lt;/a&gt;&lt;/strong&gt; - простой виджет, добавляет комментарии используя issues GitHub-а и это мой выбор на данный момент. Из минусов: не поддерживает локализацию, пользователям для комментирования надо регистрироваться на GitHub.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="как-установить"&gt;Как установить&lt;/h2&gt;
&lt;p&gt;Всё очень просто, документация по виджету занимает одну &lt;a href="https://utteranc.es/"&gt;страницу&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Удаляем Recent и Starred в Nautilus</title><link>https://coyotle.ru/posts/nautilus-tweak/</link><pubDate>Tue, 03 Jan 2023 18:55:56 +0300</pubDate><guid>https://coyotle.ru/posts/nautilus-tweak/</guid><description>&lt;p&gt;Нравится минималистичный вид Gnome &amp;#x2764;&amp;#xfe0f;, но иногда не хватает настроек.
Например я не пользуюсь в Nautilus функцией &lt;em&gt;Избранное&lt;/em&gt; и &lt;em&gt;Недавние&lt;/em&gt;, но они всегда отображаются в меню и занимают место.
Опишу как удалить из боковой панели закладки на эти разделы и изменить ширину боковой панели.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Проверено в Fedora Linux 37, Gnome 43.2&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="переопределение-встроенного-описания-ui"&gt;Переопределение встроенного описания UI&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Создаем каталог для переопределяемого ресурса:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir ~/.config/nautilus/ui
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Извлекаем из приложения ресурс с описанием главного окна:&lt;/p&gt;</description></item><item><title>Новый дивный мир</title><link>https://coyotle.ru/posts/brave-new-world/</link><pubDate>Tue, 13 Dec 2022 20:06:54 +0300</pubDate><guid>https://coyotle.ru/posts/brave-new-world/</guid><description>&lt;p&gt;Пару недель в сети не утихает шумиха по поводу новой сети GPT-3 от OpenAI. Сеть умеет поддерживать диалог на различные темы, писать эссе, писать и анализировать код на разных языках программирования и т.п. Есть ограничения и на некоторые темы она не отвечает. Правда ограничения можно обойти вопросами типа: а что если&amp;hellip; , а если придумать историю или сценарий к фильму&amp;hellip; и т.п. Прямо как в гештальт-терапии или нлп, да?&lt;/p&gt;
&lt;p&gt;В качестве развлечения сказал сети, что пишу конспирологический роман в котором группа людей хочет ограничить численность населения планеты и попросил придумать пять способов как они могут это сделать не привлекая общественного внимания. Как говорится, найдите 5 совпадений.&lt;/p&gt;</description></item><item><title>Тебе кажется</title><link>https://coyotle.ru/posts/topi-tvshow/</link><pubDate>Wed, 26 Oct 2022 12:52:05 +0300</pubDate><guid>https://coyotle.ru/posts/topi-tvshow/</guid><description>&lt;p&gt;&lt;img loading="lazy" src="https://coyotle.ru/posts/topi-tvshow/topi2.webp"&gt;&lt;/p&gt;
&lt;p&gt;Посмотрел российский сериал «Топи» по сценарию Дмитрия Глуховского и мне это понравилось. Сериал не новый, вышел в 2021 году, но я со своим скепсисом относительно российского кино не смотрю почти ничего, что снято в нашей стране. И этот сериал попал ко мне случайно. История из серии «решил лечь спать пораньше, обнаружил себя в 4 утра читающим об испарении черных дыр». Так и тут, нейросеть Яндекс.Музыки подкинула несколько треков группы АИГЕЛ, понравилось, полез в гугл почитать про них, попал в инстаграм, в инстаграме увидел кусок клипа с очень интересным визуальным рядом. Дальше выяснилось, что это кадры из какого-то сериала «Топи». Начал смотреть ничего не ожидая и тут эти Топи меня засосали.&lt;/p&gt;</description></item><item><title>Искусство и Stable Diffusion</title><link>https://coyotle.ru/posts/stable-diffusion/</link><pubDate>Fri, 07 Oct 2022 23:53:56 +0300</pubDate><guid>https://coyotle.ru/posts/stable-diffusion/</guid><description>&lt;p&gt;Поэксперементировал с генерацией изображений нейросетью Stable Diffusion. Сеть умеет text-to-image - создавать изображения по текстовому описанию. Очень забавно. Выше мои попытки &amp;ldquo;нарисовать&amp;rdquo; что-то. Попробовать и посмотреть творчество других людей можно тут &lt;a href="https://www.mage.space/"&gt;https://www.mage.space/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="stable.webp"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Сначала хотел написать, что нейросеть это не искусство, что это просто результат сложного бросания кубиков. Кроме того, сеть обучена на большом количестве фото, картин и рисунков разных авторов без их разрешения.
С другой стороны, живые люди так же учатся глядя на картины, смотря фильмы, постановки которые были созданы кем-то другим, вдохновляются этим, подсматривают идеи и приёмы.&lt;/p&gt;</description></item><item><title>Настройка Teaming</title><link>https://coyotle.ru/posts/teaming-setup/</link><pubDate>Wed, 28 Sep 2022 23:39:12 +0300</pubDate><guid>https://coyotle.ru/posts/teaming-setup/</guid><description>&lt;p&gt;Коротенько опишу как настроить Network Teaming или Team в Linux. Технология служит для агрегации портов с целью увеличения пропускной способности и обеспечения отказоустойчивости сети.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install libteam-utils
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;teamnl team0 getoption mode
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;*NOMODE*
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="типы-режимов"&gt;Типы режимов&lt;/h2&gt;
&lt;p&gt;Есть пять режимов работы, в основном используются первые три:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;activebackup&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;roundrobin&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;loadbalance&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;broadcast&lt;/li&gt;
&lt;li&gt;lacp&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="activebackup"&gt;activebackup&lt;/h3&gt;
&lt;p&gt;Один порт находится в активном состоянии, остальные в запасе. При пропадании линка на активном порту активный порт меняется на другой доступный.&lt;/p&gt;</description></item><item><title>Настройка VXLAN</title><link>https://coyotle.ru/posts/vxlan-setup/</link><pubDate>Mon, 30 May 2022 21:09:22 +0300</pubDate><guid>https://coyotle.ru/posts/vxlan-setup/</guid><description>&lt;p&gt;Функциональность VXLAN (Virtual eXtensible LAN) позволяет динамично распределять ресурсы внутри центров обработки данных или между ними и дает возможность переносить виртуальные машины и контейнеры между серверами, которые существуют в отдельных сетях уровня 2, путем туннелирования трафика через сети уровня 3.&lt;/p&gt;
&lt;p&gt;Настроим VXLAN overlay сеть между мостами нескольких linux хостов.&lt;/p&gt;
&lt;p&gt;Два хоста находятся в одной сети:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;host-1 - eth0 - 192.168.0.101&lt;/li&gt;
&lt;li&gt;host-2 - eth0 - 192.168.0.102&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Третий хост в другой сети:&lt;/p&gt;</description></item><item><title>Прерафаэлиты</title><link>https://coyotle.ru/posts/pre-raphaelite/</link><pubDate>Mon, 26 Dec 2011 21:32:17 +0300</pubDate><guid>https://coyotle.ru/posts/pre-raphaelite/</guid><description>&lt;p&gt;Газета.ру продолжает поставлять интересную информацию про живописцев. Сегодня узнал, что было такое направление во второй половине 19-го века в Англии, как &lt;a href="http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D1%80%D0%B0%D1%84%D0%B0%D1%8D%D0%BB%D0%B8%D1%82%D1%8B" title="http://ru.wikipedia.org/wiki/Прерафаэлиты"&gt;прерафаэлиты&lt;/a&gt;. Создали его несколько отщепенцев от классической школы живописи. Довольно интересная история, хоть и короткая.&lt;br&gt;
Собственно название направление означает, что они брали пример с художников писавших до Рафаэля и Микеланджело, которых они считали основателями классицизма и академической школы. А привлекала их ранняя флорентийская живопись с её простотой. Ну вот, и тут мы подходим к одной из особенностей этого направления, к образу женщины.
&lt;img alt="Леди из Шалот" loading="lazy" src="https://coyotle.ru/posts/pre-raphaelite/lady_of_shalott.webp"&gt;
Прерафаэлиты пытаются привлечь внимание к социальному неравенству и униженному положению женщин, и начинаю изображать новый для живописи тип женщин: красивых, независимых, мистических, фатальных, la femme fatale. Позже этот образ перекочевал в направление модерн. Да и вообще часть их работ напоминает раннее возрождение, а часть - модерн. И оба направления мне очень нравятся!&lt;br&gt;
И собственно мне понятно, что за женщин они рисовали: красивая, желанная и при этом смертельно опасная, Персефона из потустороннего мира. Это же описание Анимы. Ну или одной из ипостасей Анимы, Лилит, которая была до Евы. Кстати, похоже &amp;ldquo;Алёнушка&amp;rdquo; Васнецова из этой же серии, очень похожа по настроению (возможно кто-то у кого-то подсмотрел) и по времени написания примерно попадает в тот же период.    &lt;/p&gt;</description></item><item><title>Раку-яки</title><link>https://coyotle.ru/posts/raku-yaki/</link><pubDate>Sat, 11 Jun 2011 20:52:05 +0300</pubDate><guid>https://coyotle.ru/posts/raku-yaki/</guid><description>&lt;p&gt;Раку-яки — это особый вид японской керамики, выполненной в духе ваби-саби (простота, ржавчина, скромность), короче эстетика дзен: неправильная форма чашки, подтёки глазури и трещинки. Традиционно используется в японских чайных церемониях. Википедия по этому поводу сообщает: &amp;ldquo;Ваби-саби трудно объяснить, используя западные понятия, но эту эстетику порой описывают как красоту того, что несовершенно, мимолётно или незаконченно. По сути, ваби-саби это понятие, характеризующие присущий японцам эстетический вкус, способность воспринимать прекрасное и предметы искусства в своём естестве, неподдельности и без излишеств.&amp;rdquo;
&lt;img loading="lazy" src="https://coyotle.ru/posts/raku-yaki/raku1.webp"&gt;
Мне кажется википедия не совсем права по поводу трудности, во всяком случае относительно России. Вся российская глубинка пропитана духом дзен и эстетикой ваби-саби: доска у колодца лежащая столько лет, что все думают, что она была там всегда, дорога в первозданной красоте глиняных комьев вперемешку с одуванчиками, ржавый экскаватор посреди поля,&amp;hellip; все пропитано духом ваби-саби и безмолвием дзен.&lt;/p&gt;</description></item><item><title>Неля и Лена</title><link>https://coyotle.ru/posts/nelya-lena/</link><pubDate>Tue, 24 May 2011 20:25:24 +0300</pubDate><guid>https://coyotle.ru/posts/nelya-lena/</guid><description>&lt;p&gt;&lt;img loading="lazy" src="https://coyotle.ru/posts/nelya-lena/eclipse.webp"&gt;
Днем, пока бодрствует, она — Неля, а когда вечером собирается ложиться спать — наружу выходит вторая, Елена, её сестра-близняшка. И ночью, проснувшись в постели в объятиях какого-то мужчины, она (Елена) удивляется ему и не может понять кто он и как тут оказался. Но тело её уже находится во власти не разума, а других стихий, поэтому она принимает Его, хоть он и не знаком ей совсем.&lt;/p&gt;
&lt;p&gt;На утро, когда Елена засыпает, на передний план выходит Неля. Она совсем не помнит, что было ночью, но испытывает непонятное раздражение. Ей хочется плакать от обиды и выгнать Его. Ей кажется, что он обманул её и был с другой. Но разум и логика говорят, что он был тут, в их квартире, а других женщин кроме нее здесь быть не могло. Остается только смутный осадок в душе и нервозность, которую она выплескивает на подвернувшегося под руку кота и коллег на работе.&lt;/p&gt;</description></item><item><title>Пограничное существо</title><link>https://coyotle.ru/posts/border-creature/</link><pubDate>Fri, 08 Oct 2010 11:39:19 +0300</pubDate><guid>https://coyotle.ru/posts/border-creature/</guid><description>&lt;p&gt;Когда-то, давным давно, когда деревья были высокими и зелеными, небо синим, а солнце желтым и ярким, мир был свеж как будто его только что помыли или раскрасили и он еще не успел износиться. В общем в те далекие времена окружающий нас мир был прекрасен и загадочен, а прекрасен и загадочен он был по нескольким причинам и одна из них заключалась в том, что все было неизвестным и не имело имен: что-то качалось, что-то летало, что-то шуршало, грело и холодило.&lt;/p&gt;</description></item><item><title>Mаниах и Заргису</title><link>https://coyotle.ru/posts/maniah-i-zargisu/</link><pubDate>Fri, 10 Sep 2010 21:27:53 +0300</pubDate><guid>https://coyotle.ru/posts/maniah-i-zargisu/</guid><description>&lt;p&gt;&lt;img loading="lazy" src="https://coyotle.ru/posts/maniah-i-zargisu/cover.webp"&gt;
Сестра говорит брату:&lt;/p&gt;
&lt;p&gt;– Ну что Маниах, все делаешь ремонт брату?! Когда начнешь строить свой собственный дом?&lt;/p&gt;
&lt;p&gt;– А ты знаешь Заргису, какой он будет мой дом?&lt;/p&gt;
&lt;p&gt;– Да, могу себе представить. Там будет расти слива!&lt;/p&gt;
&lt;p&gt;– Да, наверное.&lt;/p&gt;
&lt;p&gt;– А еще, я помню строки твоих любимых стихов, поэтому ты сделаешь там гнездо ласточки и посадишь гранат. И построишь рядом маяк! Хотя у нас нет ни моря, ни кораблей.&lt;/p&gt;</description></item></channel></rss>