3 июля, в четверг, в 19:00 (мск) — приходите на митап про Python в Санкт-Петербурге или подключайтесь онлайн.
О чём будут доклады?
🟣 Это не те метрики, что вы ищете. Разберёмся, почему стандартного экспортёра может не хватать, и как написать свой на Python. 🟣 Кодогенерация: как компьютеры учатся писать код за нас. Поговорим про прошлое, настоящее и будущее кодогенерации в разных языках программирования. 🟣 Ruff: как не положить всё, переходя на новые правила? Поговорим про линтеры, форматтеры и подводные камни при переходе на Ruff. 🟣 Секреты успеха змеи в мире пауков. Обсудим, как мы применяли scrapy и playwright в ЮMoney, чтобы создать сервис модерации сайтов.
Нечеткое ассамблирование нейросетей для классификации на Python
Для ансамблирования нейросетей обычно используют простые методы, например, в задаче классификации, выбирают класс, за который проголосовало большинство моделей. Но что если рассматривать моделей, как экспертов, для которых мы можем оценить уровень точности? В этом посте я расскажу о своем подходе Fuzzy Vote, который использует нечеткую логику для объединения предсказаний моделей. Метод написан с помощью библиотеки fuzzyops, доступной через pypi. В библиотеке реализованы различные методы работы с нечеткими числами, поддерживаются вычисления на CUDA.
Идея метода
Каждая модель рассматривается как эксперт, который предсказывает вероятность принадлежности к классу и имеет определенную степень доверия. Эту информацию можно отразить через нечеткое число, в котором центр - это вероятность, ширина - неопределенность и высота - степень доверия.
Далее каждая модель "голосует" нечетким числом, числа агрегируются, и полученное число дефаззифицируется в одно значение. Полученное четкое число используется для классификации.
Генерация треугольного и гауссового нечеткого числа:
from fuzzyops.fuzzy_numbers import Domain, FuzzyNumber
def build_triangular(domain, centre, width, height):
a, b, c = centre - width/2, centre, centre + width/2
fn = domain.create_number("triangular", a, b, c)
return fn * height
def build_gauss(domain, centre, sigma, height):
fn = domain.create_number("gauss", sigma, centre)
return fn * height
import numpy as np
from sklearn.metrics import roc_auc_score
def evaluate_fuzzy(probs_mat, y_true, acc_vec, **kwargs):
scores = np.array([
aggregate_sample(row, acc_vec, **kwargs)
for row in probs_mat
])
scores = (scores - scores.min()) / (scores.max() - scores.min() + 1e-12)
return roc_auc_score(y_true, scores)
Как это сработало в задаче классификации пневмонии
Я обучил три модели (VGG19, ResNet50, DenseNet121) на датасете Chest X-Ray Pneumonia, взяв предобученные веса и переобучив классификатор на одну эпоху.
Результаты на валидационном и тестовом сете
Метод Fuzzy-Vote дал лучшую точность, чем любая отдельная модель или простой majority vote метод. По ROC-AUC он не обошёл VGG19, но обошёл остальные методы, включая дискретный ансамбль. При этом метод не требует сложных архитектур или переобучения: он просто работает поверх уже полученных вероятностей.
Fuzzy-Vote — это простой, но гибкий способ агрегации предсказаний с учетом точности и уверенности каждой модели. Особенно полезен в случаях, когда:
модели сильно различаются по качеству
обычный majority vote даёт просадку
хочется объединить разные модели без дополнительного обучения
Но метод еще требует доработки, он не учитывает, например, confusion matrix каждой модели, чтобы учесть ошибки разного рода. Библиотека fuzzyops позволяет реализовать метод с минимумом кода и достаточно гибкой настройкой.
С полным кодом тренировки моделей и агрегирования можно ознакомиться по ссылке.
Скачать. Бесплатно, и установка не требуется. Подробности о приложении написаны в прошлой новости. Кому нужно видеть код приложения - обновил и его. Ни на что не претендую, если больше нравится Обсидиан - никто вас не трогает.
Теперь можно менять стили редактора.
Исправлено несколько ошибок. Появилась возможность быстро создать большую структуру папок. Третья иконка слева сверху. Улучшены ИИ-функции. Да, есть и другие ИИ-функции, помимо вызова кота при клике на коробку. Открываются нажатием на волшебную палочку после нажатия по файлу. Теперь Заметки нормально работают с большим количеством файлов и автоматически удаляют из избранного файлы, которые были удалены или перемещены. Доработан интерфейс. Спасибо всем, кто ответил в комменты и на почту.
Скачать. (ссылка обновлена) Бесплатно, и установка не требуется.
Разрабатываю по фану — потому что мне самому не хватало чего-то простого, лёгкого и по делу.
Это приложение для личных заметок не претендует на звание "универсальной системы управления знаниями", не строит из себя ракетный двигатель и СОВСЕМ не пытается быть новым Обсидианом. Это просто удобное место, куда можно быстро спрятать мысль, идею или список покупок.
Что умеет:
Работает только с текстом: .txt, .md, .markdown, .mdown
Создаёт новые заметки в формате Markdown (но без наворотов — как в старые добрые)
Не держит тебя в облаке, не шифрует данные в своём формате — всё лежит на диске, как тебе привычно
Левое окно показывает структуру папок — полупрозрачные папки = пустые (нет файлов или подпапок)
Двойной клик по папке — запоминается как начальная при следующем запуске
Одинарный клик — раскрывает содержимое
Если в буфере есть текст — он автоматически попадёт в новую заметку. Буфер очищается.
Поиск: по тексту, по названиям файлов, по содержимому. С историей. А еще есть Избранное.
Настройки? Пока только для нейросетевых функций и ответов ИИ-кота (его можно позвать, кликнув по коробке), который может что-то подсказать или прокомментировать с долей сарказма.
Про искусственный интеллект:
Поддерживает OpenRouter — регистрируешься, получаешь 50 бесплатных запросов в день
Хватает за глаза для личных заметок, резюме текстов, генерации идей или перевода мыслей во что-то собранное
ИИ-кот ведёт себя не особо прилично.
В чем отличие от Обсидиана:
Обсидиан — это космический шаттл для заметок. А мы тут катаемся на велосипеде — быстро, удобно и без инструкции.
Просто. Не нужно ничего устанавливать — скачал, запустил, пишешь.
Лёгкий. Всё приложение весит 17 Мб.
Минимум функций. Не запутаешься. Никаких плагинов, графов, связей и внутренних ссылок.
Стиль свой. Не такой серьёзный, как Обсидиан.
Бесплатный ИИ здесь не только для управления, а еще для подколов и помощи.
Короче: Если устал от систем, которые требуют обучения, миграции каждые полгода... и выглядят как база данных космического корабля — это приложение для тебя. Просто открываем, пишем, сохраняем. ИИ критикует и помогает, если нужно, но не навязывается.
Горячие клавиши: Ctrl + N - создать заметку Ctrl + P - создать папку Ctrl + F - искать текст в открытом файле Ctrl + S - сохранить файл Ctrl + колёсико - изменение размера шрифта
Осваиваем азы компьютерного зрения с библиотекой Pillow на одноплатном компьютере Lichee Pi 4A
Наш первый шаг — загрузить изображение, определить его цветовую модель и получить информацию о размере и границах.
from PIL import Image
from PIL import ImageFilter
img = Image.open(“flower.jpg”)
print(img.size, img.format, img.mode)
Эта базовая информация пригодится для дальнейшей работы с изображением.
Меняем цвет пикселя
К отдельным пикселям можно обращаться с помощью метода load() из библиотеки Pillow. Так мы сможем изменять цветовые значения точечно, а это основа для различных операций по обработке изображений.
Открываем white.jpg с помощью Pillow:
from PIL import Image
img = Image.open("white.jpg")
obj = img.load()
Выбираем пиксель с координатами (25, 45) и меняем его цвет:
Метод load() позволяет напрямую работать с массивом пикселей изображения: читать, модифицировать и анализировать отдельные элементы, не копируя данные в отдельные структуры. Это особенно важно для задач, которые требуют высокую производительность при обработке больших изображений.
Почему был выбран Lichee Pi 4A, как создать виртуальное окружение Python, установить подходящую среду разработки и научиться базовым приемам работы с изображениями — читайте в подробном туториале.
Solomon Deal: как мы строим систему гарантирования сделок на TON без посредников
Как Telegram-бот, смартконтракт на Tact и теория игр позволяют заключать безопасные сделки в децентрализованной среде
TL;DR
Бот написан на Python, работает поверх Telegram
Смартконтракты на языке Tact в сети TON
Арбитраж между пользователями с мотивацией по теории игр
Судьи выбираются случайно, голосуют анонимно, получают награду
Средства хранятся только в смартконтракте, бот не имеет доступа
Бэкэнд — это сам Telegram-бот с возможностью fail-safe восстановления
Почему это вообще нужно?
Криптовалюты за последние годы доказали свою состоятельность как средство хранения стоимости и спекуляции. Но как средство обмена — по-прежнему работают слабо. Главная причина — отсутствие доверительного слоя: нет привычных гарантий, судов, посредников. Если кто-то кого-то обманул, то в децентрализованной среде — это почти всегда необратимо.
В фиатной системе роль "гаранта" берёт на себя государство. В блокчейне же — эта роль должна быть перераспределена. Мы решили попробовать построить этот слой заново: на основе смартконтрактов, Telegram и игрового баланса мотиваций.
Архитектура решения
Бэкенд: Python-бот, работающий в Telegram. Почему Telegram?
Нет необходимости в покупке DNS и выделенного сервера с белым IP, или аренды VPS
Смартконтракты: написаны на языке Tact, развёрнуты в сети TON. Исходники контракта открыты и доступны для аудита: verifier.ton.org
Взаимодействие с блокчейном реализовано через два механизма:
tonconnect — используется для взаимодействия с кошельками пользователей (предложение подписать и отправить транзакцию)
pytoniq — Python-библиотека для прямого взаимодействия с liteserver: чтение блоков, анализ транзакций, отправка собственных транзакций
Модель безопасности и хранения средств
Ключевая идея: ни бот, ни сервер не имеют доступа к средствам. Все деньги, относящиеся к сделке, проходят только через смартконтракт.
Судейская оплата (небольшие суммы) обрабатывается централизованно — чтобы избежать накладных расходов на комиссии и реализовать массовую рассылку выплат без дорогих операций на уровне блокчейна.
Если бот или сервер по каким-то причинам недоступен:
При заключении сделки пользователи получают инструкцию на случай отказа сервера
Смартконтракт включает таймер, по завершению которого средства можно разблокировать вручную, если управление смартконтрактом через бот невозможно
Разрешение споров: распределённый арбитраж
Как работает:
В случае конфликта обе стороны присылают свои версии (текст, сканы, PDF, видео)
Рандомно выбирается набор судей из числа зарегистрированных
Судьи голосуют, не зная друг друга. Механизм — Soft Majority Voting (SMV)
После последнего голоса результат отправляется в смартконтракт, и средства автоматически перечисляются победившей стороне
Мотивация:
Судьи получают награду за участие
Если судья голосует против большинства, его рейтинг уменьшается в 2 раза
Но рейтинг восстанавливается с каждым последующим делом (механизм "прощения")
Потери за ошибку размазаны на 8 последующих дел, чтобы не демотивировать участвовать
Как оформляется сделка?
Пользователи могут описывать условия простым текстом или прикладывать документы
Ни текст, ни документы не анализируются автоматически
Смартконтракт выступает только как условный хранитель средств, который получает извне команду: "перечислить A или B"
Таким образом судьи не могут украсть средства, и вся логика спора отделена от самого контракта
Сложности и находки
Работа с TON и Tact — это одновременно увлекательно и сложно. Документации по многим библиотекам либо нет, либо она устарела. Периодически приходится идти напрямую к разработчикам — и, к счастью, они действительно открыты к диалогу. Несколько багов нами были найдены прямо в приложениях кошельков и библиотек.
Что дальше?
Возможные направления развития и создание следующих модулей:
Привет, меня зовут Александр, я аналитик в Альфа-Банке. Однажды я устал, что на Feature Store, на платформе для дата-инженеров (DE) и дата-саентистов (DS), невозможно ничего найти.
Поиск по контексту отсутствует. Приходится руками шерстить огромное количество ETL-проектов в поисках той самой полезной информации, полагаясь сначала на удачу, а после — на опыт и помощь коллег.
Feature Store сама по себе — платформа, которая должна упрощать работу коллег с большими данными, упрощает бюрократию жизненного цикла создания ETL, ввода моделей в промышленную эксплуатацию. Но какой же поиск там...В общем, хотелось бы улучшить процесс по поиску данных в ней.
В данном примере мы создаём класс Pipe с перегрузкой метода __or__.
Метод __or__. был добавлен для поддержки синтаксиса X | Y, как замена typing.Union и также используется для указания, что переменная или функция могут принимать несколько различных типов значений.
import typing
int | str == typing.Union[int, str] # True
class Pipe:
def __init__(self, value):
self.value = value
def __or__(self, other):
if callable(other):
return Pipe(other(self.value))
else:
raise ValueError("Right operand must be callable")
def multiply_2(x):
return x * 2
def add_3(x):
return x + 3
changed_num = Pipe(5) | multiply_2 | add_3 # 5 * 2 + 3
print(changed_num.value) # 13
Более "сложный" пример добавил в статью как вариант для валидации атрибутов класса.
Помимо интеграции с Google Calendar, мы реализовали вложенные цепочки эскалации. Теперь в chain можно добавить другой chain (nested), благодаря чему размер конфигурационного файла уменьшится.
Мы хотим создать достаточно гибкую, но не перегруженную систему цепочек эскалации, чтобы на проектах разной величины вы могли использовать IMPulse так как вам удобно. Для этого в комментариях расскажите, какой самый сложный кейс уведомлений / эскалации вам необходимо было реализовать. Например: во вторник нужно дёргать Антона, через 5 минут Олега, а по средам - только дёргать Геннадия, в остальное время, если severity == 'critical', звонить Грише. Будем рады почитать самые сложные варианты и предложить наше универсальное решение для них.
Остаёмся на связи в нашем Telegram канале - там можно общаться / задавать вопросы.
Спойлер: принципиальное решение проблемы - найдено. Купил маленькую коробочку на "мейнстримной" архитектуре, на которой все цветет и пахнет.. кроме моего внутреннего(ну и внешнего, че уж там) инженера) Так что решение выкинуть железку - можно не предлагать
Так вот, пока я писал код, и готовил сборочные скрипты ничто не предвещало беды - я спокойно потестил код локально, написал Dockerfile для сборки на poetry. Настало время развернуть это все на NAS - казалось бы ARM уже давно мейнстрим, но тут понеслось
python как всегда лишь удобный биндинг к куче платформозависимого кода) подавляющее большинство python-зависимостей под arm/v7 приходится компилировать
готовых бинарников polars под arm/v7 - тоже нет
Никаких блокеров к тому, чтобы собрать polars под arm/v7 я не нашел. Но скомпилить его нативно на 4Гб ОЗУ - не получится, даже с минимальными оптимизациями. Нужна кросс-компиляция. Благо с rust и maturin(которым собирается polars) - это несложно, target armv7-unknown-linux-gnueabihf в хорошем tier-е поддержки
забегая чуть вперед указываем окружение для сборки аллокатора jemalloc(по умолчанию в polars) под 32k страницу
Итак, усложняем сборку Docker(см. repro) - используем кросс-компиляцию, энв-переменные, QEMU, охапку дров и теперь у нас есть приложка, которая успешно стартует в докере на целевой железке. Вот только за рамками самых примитивных тестов - OOM-ится, причем память точно есть, никакой OOM-киллер процесс не убивает(на всякий случай смотрим лимиты cgoup) - оно "шамо":
memory allocation of 1345920 bytes failed
(подробные логи можно посмотреть по ссылкам в конце поста)
Что же делать?
пробуем mimalloc - он использует для конфигурации рантайм(getconf), эффект - тот же
пробуем env-крутилки, в частности arena_reserve может стоит просто меньше резервировать - но нет, просто больше попыток, но по факту все равно OOM
И вот на этом месте я застрял. Я не большой спец по системному программированию - не понимаю куда копать
Общение с поддержкой QNAP свелось к
Справедливости ради они еще дали советов что попробовать, но это я уже попробовал до них
Пытался отлаживать приложение в gdb - никаких аномальных трейсбэков во время OOM не увидел: rust честно пытается аллоцировать большой raw_vec(трейс есть в вопросе на stackoverflow)
Как-то глубоко копать переменные не получается, т.к. дебаг-символы для бинарника polars получаются слишком большими
BFD: error: /app/.venv/lib/python3.12/site-packages/polars/polars.abi3.so(.debug_str) is too large (0x498a9fd1 bytes)
Я сделал небольшое repro на голом расте - там эта проблема не воспроизводится, значит базово бинарная совместимость - в порядке
Есть несколько гипотез, но я не знаю как их проверить
возможно, кривая вся адресация, но ее проверить я тоже не могу
возможно, стоит чего-нибудь половить в ядре bpf-ом, но что..
кастомное ядро 4.2.8 кастомный дистриб(QTS) не богат средствами отладки - как я понял там запускается busybox набор утилит
А мне бы хотелось все-таки дожать диагностику и однозначно ответить на вопрос: это лыжи не едутя не умею собирать приложения под нужное окружение или все-таки целевая платформа не умеет выполнять корректно собранное? Не потому что эту проблему нельзя решить по-другому, а потому что в том, чем пользуешься - хочется разбираться.
Пишите в комментах ваши соображения. Если что-то удастся прояснить - буду держать читателей поста в курсе
Мы все с вами привыкли, что в питоне можно "зарайзить" исключение в любой момент: raise Exception Но, что если в какой-то момент времени мы не можем вызывать исключение?
Простейший пример: что произойдет при запуске такого скрипта?
# ex.py
class BrokenDel:
def __del__(self):
raise ValueError('del is broken')
obj = BrokenDel()
del obj
print('done!') # будет ли выведено?
Тут может быть два варианта:
Или del вызовет ValueError и программа завершится
Или случится какая-то магия, ошибка будет вызвана, напечатается, но программа продолжится
» python ex.py
Exception ignored while calling deallocator :
Traceback (most recent call last): File "/Users/sobolev/Desktop/cpython/ex.py", line 3, in __del__ raise ValueError('del is broken')
ValueError: del is broken
done!
Знакомьтесь – unraisable exceptions 🤝
Как оно работает?
В некоторых местах C кода у нас есть необходимость вызывать исключения, но нет технической возможности. Пример, как выглядит упрощенный dealloc для list?
static void
list_dealloc(PyListObject *op)
{
Py_ssize_t i;
PyObject_GC_UnTrack(op); // убираем объект из отслеживания gc
if (op->ob_item != NULL) {
i = Py_SIZE(op);
while (--i >= 0) {
// уменьшаем счетчик ссылок каждого объекта в списке
Py_XDECREF(op->ob_item[i]);
}
op->ob_item = NULL;
}
PyObject_GC_Del(op);
}
А, как вы можете знать, чтобы в C коде вызвать ошибку, нужно сделать две вещи:
Взывать специальное АПИ вроде PyErr_SetString(PyExc_ValueError, "some text")
И вернуть NULL как PyObject * из соответствующих АПИ, показывая, что у нас ошибка. Если вернуть NULL нельзя, то мы не можем поставить ошибку в текущий стейт интерпертатора. А тут у нас void и вернуть вообще ничего нельзя. Потому приходится использовать вот такой подход с unraisable exception
Они создают ошибку, но не выкидывают её обычным способом, а сразу отправляют в специальный хук-обработчик. Данный хук не производит классическое "выбрасывание" исключения, а просто его печатает по-умолчанию. Ниже посмотрим, как его можно кастомизировать.
В питоне оно используется где-то 150 раз. То есть – прям часто. Примеры:
Ошибки при завершении интерпретатора, попробуйте сами:
Я сделал своего первого Telegram-бота — WebCheck. Мониторинг сайтов прямо в Telegram
Привет!
Меня зовут Александр, и я решил поделиться с вами своим первым публичным Telegram-ботом. Я давно хотел реализовать что-то полезное и практичное — в итоге получилось то, чем сам теперь пользуюсь каждый день.
Знакомьтесь: WebCheck— бот, который следит за доступностью сайтов, SSL-сертификатами и доменами.
🧠 Что умеет бот
Проверяет, доступен ли сайт (HTTP-код);
Показывает, сколько дней осталось до окончания SSL-сертификата;
Проверяет, когда истекает регистрация домена;
Присылает уведомление, если:
сайт стал недоступен;
до окончания SSL-сертификата осталось 14 дней или меньше;
до окончания регистрации домена осталось 14 дней или меньше;
Позволяет экспортировать логи и список сайтов в CSV;
Есть админ-интерфейс для контроля всех добавленных сайтов.
Получаете оповещения, если с ресурсом что-то не так
Бот абсолютно бесплатный, ничего не требует — просто добавил сайт, и бот сам всё контролирует.
👨💻 Технически
Бот написан на Python с использованием:
aiogram v3
PostgreSQL
APScheduler
Shell-команд (whois, curl, openssl) для большей точности
Контейнеризирован в Docker, база хранится вне контейнера, а вся логика максимально простая и прозрачная.
🔐 А ещё я сделал бот для дешифровки VNC
Если вдруг работаете с .vnc файлами или UltraVNC — может пригодиться мой мини-инструмент: @DecryptVNC_bot— он расшифровывает VNC-пароли прямо в Telegram.
🙏 Буду рад, если протестируете
Это мой первый бот, и я был бы благодарен за фидбек. Если найдёте баг, захотите предложить улучшение — пишите. Буду дорабатывать и развивать.
Новый тайпчекер для Python от авторов ruff и uv, написанный на Rust
Вышло видео про новый тайпчекер и lsp: ty (старое название red-knot) от авторов ruff и uv. Пока по первым впечатлениям – бомба! Не смотря на версию 0.0.0a8 🌚
Из плюсов:
Быстрый
На расте
Куча новых фичей для типов
Полная спецификация
Интеграция с ruff и IDEшками
Из минусов:
Пока есть баги (но их поправят, конечно же)
Нет плагинов (и скорее всего никогда не будет)
Софт от молодой и маленькой компании
Как сделать поддержку ty и mypy вместе? А если использовались ty_extensions?
Представлен бесплатный гайд по изучению языка программирования Python за 100 дней от истории создания языка и его работы на уровне процессора и памяти до мощнейших фреймворков и комплексных алгоритмов. Задачи равномерно распределены. Каждый урок объёмный и разжеван досконально — поймет даже полный нуль в кодинге. Любое объяснение подкрепили примерами кода.После разделов есть сборники задач разного уровня сложности, чтобы железно зафиксировать знания.
Недавно ревьюил один интересный PR в CPython: в питон добавили еще один способ форматировать строки. Теперь – со специальным АПИ для внешних интеграций. Расскажу: как и зачем.
Основная причина: использовать f строки удобно, но нет никакого АПИ для перехвата момента "вставки" или интерполяции значений. Например, при форматировании html или sql – требуется специальным образом делать escape для значений. И раньше код вида f"{template}" представлял собой дыру в безопасности и потенциальное место для XSS.
string.templatelib.Template
Новый префикс t не будет создавать объект str, он будет создавать объект класса string.templatelib.Template:
Обратите внимание, что при создании template – у нас не произошло форматирование сразу. Мы создали объект, у которого есть свойства strings и interpolations, из которых можно собрать финальную отформатированную строку.
Давайте посмотрим на примере. Допустим, мы хотим формировать URL из наших данных:
>>> domain = 'example.com'
>>> query = 'python string formatting is too complex'
>>> template = t'https://{domain}?q={query}'
И сам код логики форматирования, где мы будем вставлять значения разным способом. Если у нас шаблон query, то мы будем использовать quote_plus для его форматирования. Остальные значения – будем вставлять как есть:
>>> from string.templatelib import Template, Interpolation
>>> from urllib.parse import quote_plus
>>> def format_url(template: Template) -> str:
... parts = []
... for part in template:
... match part:
... case str() as s: # regular string
... parts.append(s)
... case Interpolation(value, expression='query'):
... parts.append(quote_plus(value))
... case Interpolation(value):
... parts.append(value)
... return ''.join(parts)
Сегодня я исправил баг с типизацией, который случайно нашёл когда делал ошибки.
Вот этот отрывок: void main() { int x = "h"; } обрабатывался как правильный синтатикс. Теперь нет.
И я добавил цикл do-while. Правда в нём есть проблема: в конце если выражения = false то он ещё раз выполняет и потом останавливает цикл do-while. Ну, пока что так.
Пример цикла do-while:
void main() {
int a = 10;
do {
a = a + 1;
} while (a > 2);
}
Только вывод не то что "a" это 1 а 0. Правда, сил нету добавлять ненужные части кода для исправления.
Ну. Хотя бы работает как то. А то когда в первый раз делал этот цикл то вообще нечего не работало.
От картотеки Лумана к современным графам: учим языки программирования с методом Цеттелькастен
В середине XX века социолог Никлас Луман разработал метод организации информации Цеттелькастен (Zettelkasten). Он создавал множество заметок и, чтобы не терять знания, начал вести картотеку. Система нумерации и ссылок помогала ориентироваться в карточках. У каждой заметки был уникальный номер, отражающий тему и дополнения.
Спустя полвека идеи Лумана остаются актуальными. Более того, появились программные обеспечения для ведения базы знаний. Заметки сохраняются в облаке и отображаются в виде графа.
Все заметки Дмитрия в виде графа
Веб-разработчик в YADRO Дмитрий сохраняет заметки в сервисе Obsidian. Дмитрий услышал о ПО от инженера и блогера Николая Тузова и понял, что система, похожая на картотеку, ему близка.
Программа оказалась понятной, легко адаптируемой под разные задачи. Когда Дмитрий перенес данные из Notion в Obsidian, образовалось несколько графов: по Go, хешированию и базам данных. В этой базе знаний все концепции в Go пересеклись в двух точках — интерфейсе и горутинах. Есть еще слайсы, но в основном все «лучи» сходятся именно в эти две точки.
Как Дмитрию удалось упорядочить большие объемы знаний и кому он рекомендует Цеттелькастен, читайте в статье →
Сегодня на данный момент я пишу компилятор C в байткод.
Вы скажете: но C же в машинный код компилируется? В моём случае нет. Лишь в байткод.
Вот правила которые мой C поддерживает:
цикл do-while, цикл while, условие if-else, цикл for (возможно)
Из операций: +, -, /, *, ==, !=, <, >
Декларация переменных только с инициализацией (не int x;) а (int x = 5;)
Присваивание (типо a = a + 1;) можно при созданной переменной
Из типов данных только два: int, char
Функции не обещаю но возможно будут
А то что уже есть:
if-else, while
Декларация переменных
Присваивание переменных
Все типы данных
Все операции
Сделать факториал уже можно. Вот пример факториала 5:
int n = 5;
int f = 1;
while (n > 1) {
f = f * n;
n = n - 1;
}
Вывод:
Execution finished
n: 0
f: 120
Вот как он работает:
С помощью регулярок лексер получает нужный токен и тег
Парсер строит AST
Компилятор делает байткод
Виртуальная машина выполняет его
Вот так всё работает.
Все инструкции байткода (на данный момент):
FETCH переменная - положить на стек значение переменной
PUSH число - положить на стек число
POP - я не помню зачем это ведь это не нужно будет нам
ADD, SUB, MUL, DIV - бинарные операции
NOTEQ, EQ, LT, GT - реляционные операции
JMP адрес - перейти по адресу
JNZ адрес - перейти по адресу если на вершине стека не 0
JZ адрес - перейти по адресу если на вершине стека 0
PASS - игнорировать
STORE имя - сделать переменную если она есть и её тип данных
соответствует типу данных значения
TSTORE имя - декларация переменной
HALT - конец программы
Вот так. На данный момент в проекте где-то 400 строчек кода но это с комментариями и всеми пустыми строками.
Опубликовано исследование о том что индексирование сайтов поисковиком (Google) не зависит от того, SPA ли это или же он SSR. Также пару лет назад делал аналогичное расследование и пришел к тому же выводу.
Вообще, мы пришли к идеалу достаточно давно - когда сервер занимается своими делами, а клиент статический, минифицирован, и раздается из CDN для быстроты и без траты ресурсов сервера.
Увидел сегодня на русском Stackoverflow один не отвеченный вопрос про то, как понять, какой метод с двойным подчёркиванием будет вызван, если в выражении будет использован тот или иной оператор.
Не очень было понятно, как можно извлечь эту информацию из самого Питона, не заглядывая в готовые таблицы соответствия (это было бы скучно). Тем более, что на самом деле Питон много чего оптимизирует, и на самом деле при сложении двух сущностей обычно не будет вызван метод __add__, а в байткоде сгенерируется вызов BINARY_ADD, в чём можно легко убедиться с помощью модуля dis (если речь не о самописном классе с перегруженным методом __add__, а о каких-то стандартных объектах Питона). Например, сложим два списка через + и через __add__ и посмотрим, какой байткод будет сгенерирован.
И тут я вдруг вспомнил про стандартный модуль operator, в который зашиты все возможные операторы Питона именно в виде именованных методов как с двойным подчёркиванием, так и без оного. После небольшого исследования оказалось, что в нём каждый такой метод имеет строку документации, в которой таки написано что-то типа "Same as a + b." ("Тоже самое, что a+b.")
То есть мы хотя бы можем извлечь табличку соответствия операторов и этих методов прямо изнутри самого Питона. В результате был написан следующий код.
# Модуль operator содержит методы, аналогичные встроенным методам Питона и методам классов Питона
import operator
import re
# Будем искать в докстрингах методов фразу "Same as" ("То же, что и")
rx = re.compile('Same as (.*)')
# Перебираем имена модуля operator
for name in dir(operator):
# Нас интересуют только имеющие двойное подчёркивание в названии
if '__' in name:
# Берём аттрибут модуля operator с таким именем
attr = getattr(operator, name)
# Читаем его docstring и ищем там фразу (см. выше)
descr = rx.findall(attr.__doc__)
# Если фраза нашлась, то она там одна и заканчивается она точкой, которая нам не нужна
if descr:
print(f'{descr[0][:-1]} -> {name}')
Получилось такое соответствие.
abs(a) -> __abs__
a + b -> __add__
a & b -> __and__
a + b, for a and b sequences -> __concat__
b in a (note reversed operands) -> __contains__
del a[b] -> __delitem__
a == b -> __eq__
a // b -> __floordiv__
a >= b -> __ge__
a[b] -> __getitem__
a > b -> __gt__
a += b -> __iadd__
a &= b -> __iand__
a += b, for a and b sequences -> __iconcat__
a //= b -> __ifloordiv__
a <<= b -> __ilshift__
a @= b -> __imatmul__
a %= b -> __imod__
a *= b -> __imul__
a.__index__( -> __index__
~a -> __inv__
~a -> __invert__
a |= b -> __ior__
a **= b -> __ipow__
a >>= b -> __irshift__
a -= b -> __isub__
a /= b -> __itruediv__
a ^= b -> __ixor__
a <= b -> __le__
a << b -> __lshift__
a < b -> __lt__
a @ b -> __matmul__
a % b -> __mod__
a * b -> __mul__
a != b -> __ne__
-a -> __neg__
not a -> __not__
a | b -> __or__
+a -> __pos__
a ** b -> __pow__
a >> b -> __rshift__
a[b] = c -> __setitem__
a - b -> __sub__
a / b -> __truediv__
a ^ b -> __xor__
К чему это всё? Да просто люблю исследовать Питон. Благо он позволяет легко извлекать из себя и обрабатывать такие штуки, которые из других языков бывает довольно непросто вытащить даже с применением каких-то специальных библиотек. А в Питоне всё это стандартными методами и встроенными библиотеками делается буквально в несколько строк кода.
Напоминаем, что в Академии Selectel можно пройти бесплатный курс «Изучаем Python: теория, практика, настройка инструментов».
Вы наверняка уже знаете основы. Не будем понапрасну расходовать ваше время и поможем сделать первые шаги в мире реального программирования. Курс сжатый — на изучение уйдет вечер.
Что будем делать:
✅ настроим инструменты разработчика — уделим внимание связке IDE и Python;
✅ поработаем с базами данных и брокерами сообщений — будем писать запросы SQL;
IMPulse - менеджмент инцидентов. Интеграция с Telegram.
После первой публикации об IMPulse, стало понятно, что основная интеграция, которую от нас ждут, это Telegram. И мы рады её представить!
Для работы с Telegram мы использовали группы с топиками - они лучше всего ложатся на наш функционал. В процессе разработки мы столкнулись с багом при упоминании (mention) пользователей в Telegram, о чём составили соответствующий issue. Если вы тоже заинтересованы в закрытии этого бага, пожалуйста поставьте "👍".
Помимо интеграции с Telegram стоит упомянуть реализованный шедулер для работы команд реагирования по расписанию. Синтаксис конфигурации составлен таким образом, чтобы в будущем была возможность интегрироваться с внешними календарями типа Google.
c 2016 года был аккаунт на Reddit. Читал и постил исключительно только в форум по Python (1 млн. подписчиков!). Вчера неожиданно получил теневой бан. То есть твои комментарии и посты никто не видит. Фактически это read only.
Сделал несколько новых аккаунтов с разных IP и устройств. Оказалось теперь не надо верифицировать email. Это занимает 15 сек. На части аккаунтов почту верифицировал - это не помогло. Вот пример только созданного аккаунта без почты, на нем ничего не делалось и потому он еще жив: https://www.reddit.com/user/No-Half8140/
Если у вас есть возможность получить код на почту вида dff35fghf@hfhlltgf.com, то вам автоматически дадут бесплатно PRO версию аккаунта - это расширенная статистика и другие плюшки, но все равно состояние "перед баном".
При проверке работоспособности выяснилось, что все новые аккаунты находятся в состоянии "перед баном". Это значит можно менять аватарку, можно читать, голосовать, аккаунты видны с разлогиненного устройства или из приватного окна браузера.
При попытке сделать пост на свою собственную стену (автоматически появляется при регистрации), написать любой комментарий в любую ветку обсуждения (даже в /askReddit и даже /NewToReddit), создать пост в любых группах и даже пригласить человека модератором на свою стену, а также сделать Follow на человека без кармы - мгновенный теневой бан. Аккаунт не виден из приватного окна и с разлогиненных устройств, аватарка меняется на красный и ее невозможно изменить.
Для всех IP и языков (english, poland, русский ) симптоматика одинаковая. ChatGPT говорит, что, да, теперь так, бан очень вероятен. Однако, я вижу в группах о Москве и Питере некоторую активность, значит как-то людям удается пройти этот квест.... Но как?
По статистике, специалисты по Data Science тратят до 70% рабочего времени на этап Feature Engineering, то есть отбирают наиболее важные признаки в данных и формируют новые, более информативные, датасеты. Кажется, с этой рутинной задачей отлично справится LLM. Но нет — в итоге 64% времени уйдёт на подготовку промптов.
Исследователи предлагают новые решения проблемы, одно из них — FELIX(Feature Engineering with LLMs for Interpretability and Explainability). Всё, что нужно для получения готовых фич — сам датасет и его короткий контекст. Дальше FELIX делает следующее:
Из случайных групп сэмплов датасета LLM генерирует численных и категориальных кандидатов в новые признаки.
С помощью кластеризации эмбеддингов похожие признаки отбрасываются.
Из полученных признаков отбрасываются те, что дают наименьшую объяснимость.
Метод эффективен для текстовых данных и сильно превосходит TF-IDF и трансформерные эмбеддинги от RoBERT. Если вам интересно, расскажем и о преобразовании других типов данных в новых постах!
$ fasm example.asm example
$ ld example -o example
$ ./example
Hello, World!
А сам код генерируется такой:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Author: alexeev-prog ;;
;; Example ASM Program ;;
;; Program generated by FLEXPASM (github.com/alexeev-pro/flexpasm) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
format ELF64 executable 3; ; ELF64 EXECUTABLE
entry start ; Set Start Entry
;; Segment readable executable in FASM is a directive for defining a section of code with readable and executable attributes.
segment readable executable
start: ; Label start with 7 commands
MOV RAX, 4 ; Loading 4 value into RAX register.
MOV RCX, message ; Loading message value into RCX register.
MOV RDX, message_size ; Loading message_size value into RDX register.
INT 128 ; Call software interrupt 128: SYSCALL
MOV RAX, 1 ; Loading 1 value into RAX register.
MOV RBX, RBX ; Exclusive OR operation RBX and RBX using XOR
INT 128 ; Call software interrupt 128: SYSCALL
;; Segment readable writeable in FASM is a definition of a segment of program data codes, where the attributes readable (the contents of the segment can be read) and writeable (program commands can both read codes and change their values) are specified for it.
segment readable writeable
message db 'Hello, World!', 0xA ; Var message (string)
message_size = $-message ; Var message (string) length
Я его написал довольно давно, вот решил поделиться. Может кому-то пригодится. Если есть баги - создавайте PR и Issue, буду рад)
Пользователь Reddit рассказал, что проанализировал с помощью нейросети Claude 3.7 EXE-файл на Visual Basic 27-летней давности и смог с помощью простого промта провести реверс-инжиниринг программы так, чтобы нейросеть переписала её на Python.
Это была старая программа на Visual Basic 4, написанная в 1997 году. Запуск exe-файла VB4 в 2025 году может стать настоящим кошмаром совместимости, требующим поиска устаревших DLL и сложных обходных путей.
Пользователь загрузил файл exe в Claude 3.7 с таким запросом: «Можете ли вы сказать мне, как запустить этот файл? Было бы неплохо преобразовать его в Python».
Claude 3.7 проанализировала двоичный файл, извлекла токены VB (VB не является языком, полностью компилируемым в машинный код, что делает эту задачу намного проще, чем что‑то из C/C++), идентифицировала элементы пользовательского интерфейса и даже извлекла звуковые файлы.
Затем нейросеть сгенерировала полный эквивалент приложения на Python с помощью Pygame. По словам автора, код заработал с первой попытки, и весь процесс занял менее пяти минут.
Интерактивный стримкаст со зрителями 9 марта в 19:00
Максим будет писать веб интерфейс для вики (с выделением текста и возможностью отставлять инлайн комментарии) с помощью последней версии Copilot agent. А все мы (включая вас) — токсично (и не очень) комментировать.
Авторы метода подсмотрели идею Loss Aversion в экономической теории Канемана и Тверски.
Основная идея для метода: люди склонны переоценивать низкие вероятности возникновения альтернатив и недооценивать высокие. Кроме того, приобретенная ценность в результате действий оказывается менее значительной, чем потеря такой же ценности, и даже при малом риске потерь люди склонны отказываться от него.
Авторы вводят Human-Aware Loss, который моделирует такое восприятие. Здесь уже не нужны пары ответов модели: достаточно иметь бинарную оценку, которая показывает «хороший» он или «плохой». Лосс сначала оценивает относительную награду, используя референсную политику — вероятность получить тот же ответ, используя модель до начала дообучения. После этого относительная награда максимизируется с учетом KL-дивергенции и заданного желаемого промежута между хорошими и плохими ответами.
Плюсы метода:
Очень простой сбор датасета. Достаточно просить пользователя после ответа поставить лайк или дизлайк. А уже существующие парные датасеты увеличиваются в 2 раза автоматически.
Более устойчивый метод, чем DPO и PPO.
Не использует прямую генерацию референсной модели, сильно повышая эффективность по памяти и скорости работы.
На достаточно больших моделях 13B+ не требует SFT.
Минусы метода:
Не показано качество работы на больших моделях 30B+.
Нужно уделять больше внимания датасету при переработке его из других форматов. Проблема может крыться в транзитивности A>B>C. В датасете DPO будет A>B, B>C. В датасете KTO окажется, что A — хороший пример, C — плохой, а B один раз хороший, а другой плохой, и мы будем пытаться по-разному отметить один и тот же пример.
Необычное! Исходник прототипа игры Пинг-Понг на MatPlotLib (научная графика на python) с высоким FPS .
Ранее в моей >>статье на Хабр было рассмотрено применение PyGameдля построения графиков, а теперь, наоборот, делаем игру на системе построения научных графиков. В предыдущей версии при попытке вывода текста с высоким FPS возникали сильные "тормоза", В текущей версии эта проблема решена.
В коде для отрисовки всех элементов игры используются только объекты MatPlotLib: теннисные ракетки - это столбцовые диаграммы, мячик - это scatter диаграмма, само игровое поле - это объект figure из MatPlotLib, текст также выводится через встроенные в MatPlotLib функции. Для анимации используется встроенный в MatPlotLib объект Animation + update(). FPS=40 (сорок!).
P.S. желтая столбцовая диаграмма - это распределение координат по оси Y, в которых ракетка отбивает мячик. Обновляется при каждом ударе ракеткой по мячику.
Представлен локальный ИИ-ассистент DeepSeek Code Companion для разработчиков на базе DeepSeek R1. Для работы с ним не нужен даже API. Пишет код на уровне сеньора. Во время компиляции помогает в отладке и исправлении багов. Даёт рекомендации по архитектуре и масштабированию. На выбор есть две модели: для быстрых ответов и для более сложных задач.
Из комментариев к статье о гитарном тюнере выяснилось, что многие НЕ верят, что можно вычислять ОЧЕНЬ ТОЧНО частоту синусоидального сигнала по очень небольшому количеству отсчетов не равному степени двойки для FFT и намного точнее чем FFT на том же количестве отсчетов и том же временном интервале накопления данных. Например, ошибка определения частоты может быть 0.05 Гц при небольшом количестве отсчетов на интервале 0.1 сек (FFT дало бы ошибку в 10 Гц = 1/0.1 сек) . Однако, кажется, это возможно. Вот ссылка на мой код на Python (>>исходник) (в телеграм) Коллеги, прошу проверить код, возможно я где-то ошибся.
Actual frequency: 5.77 Hz
Estimated frequency: 5.769999999999999 Hz
Frequency estimation error: 8.881784197001252e-16 Hz
Мы будем ждать ваших сообщений до 2 марта 2025 года, после чего подведем итоги. 10 счастливчиков получат комплект мерча Selectel: картхолдер, кружку и плюшевого Тирекса 🦖
Если готового бота у вас еще нет и вы вообще таким не занимались, то у нас в Академии Selectel есть пример для вдохновения — пошаговый гайд по созданию бота для прогноза погоды. На всякий случай есть еще инструкция, как задеплоить бота на сервер (мало ли).