Pull to refresh
8K+
3
1,7
Rating
Send message

Какую замену использовать для STFW?

Дисклеймер: Пост несет юмористический характер и не ставит своей целью оскорбить или дискриминировать кого-либо.

В своей практике иногда отвечаю на некоторые вопросы STFW, но прогресс не стоит на месте, и сейчас всё чаще актуальным ответом может быть ATFAI (Ask The F*****g AI), однако я не нашел какого-либо устоявшегося варианта на этот случай. Решил воспользоваться ATFAI и получил следующий ответ (внимание нейрослоп):

Аббревиатура ATFAI (как Ask The F*****g AI) грамматически и логически абсолютно подходит и идеально ложится в канон старого гиковского сленга. Она построена ровно по тому же принципу, что и её «предки».

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

1. Самый близкий к оригиналу: RTFAI

  • Расшифровка: Read The F*****g AI (или Run The F*****g AI).

  • Почему это лучше: Абсолютно мимикрирует под легендарную RTFM. Визуально меняется всего одна (последняя) буква. Любой айтишник или заядлый пользователь интернета мгновенно считает отсылку на ментальном уровне, даже если видит это сокращение впервые.

  • Контекст: «Чувак, этот код пишется в одну строчку, RTFAI».

2. Максимально точный: STFAI

  • Расшифровка: Search The F*****g AI (или Smartly Task F*****g AI).

  • Почему это лучше: Прямой наследник STFW (Search The F*****g Web). Отражает суть действия — вместо поисковика человек должен был пойти в строку ввода нейросети.

  • Контекст: «Зачем ты спамишь в чат базовыми вопросами? STFAI».

Как вы считаете, какой из предложенных вариантов ATFAI, RTFAI или STFAI лучше и точнее отражает смысл и годится для внесения в канон? Может быть у вас есть альтернативный вариант?

Tags:
+3
Comments0

На сколько модели MLX работают быстрее GGUF на MacBook с 24GB RAM?

На Хабре есть несколько статей от счастливчиков, которые используют довольно хорошее железо в виде MacBook Pro с 48-64GB RAM, и я полностью согласен, что у разработчика должно быть что-то подобное. Но часто бывает, что такое железо не по карману, а хочется понимать, на сколько реален профит от использования оптимизации MLX на чипах Apple Silicon. В статьях обычно указывается средняя разница в 10-30% между GGUF и MLX версиями моделей. Почему, собственно, возникла такая идея? Потому что не для всех моделей есть MLX версия, и стоит ли выбирать модель, где она есть, если у схожей модели, которая вам больше нравится, MLX версии нет.

Этот пост не тянет на серьезное исследование или статью, а представляет собой результаты небольшого эксперимента. Было желание сравнить скорость работы по критерию eval rate  для условно "легких", "средних" и "тяжелых" моделей в двух версиях GGUF и MLX.

Для эксперимента я воспользовался MacBook Air M4 24 GB (да, это был не Pro, но хотелось проверить модели > 30b, а Pro вариантов с подходящей памятью не нашлось), LM Studio 0.4.21 (по причине того, что Ollama v. 0.33.0 для больших моделей установила минимальное ограничение 32GB RAM, и если оно ниже, то принудительно использует движок GGUF). Я выбрал такие модели, допустимые для запуска на этой конфигурации:
- "легкая" модель qwen2.5-coder:1.5b (вариант для автозаполнения)
- "средняя" модель qwen2.5-coder:14b (вариант для генерации скриптов)
- "тяжелая" модель qwen2.5-coder:32b (вариант для выбора архитектурных решений и подходов к реализации).
Для чистоты эксперимента каждый тест делался в новой сессии, никакие иные приложения не запускались, чтобы минимизировать использование памяти.

Небольшое допущение: модели MLX я брал из репозитория mlx-community, но с таким же уровнем квантования, как и GGUF модели. Для тестов я использовал 3 промта соответствующего уровню модели сложности, в результатах приведены усредненные значения eval rate.

"Легкие" модели qwen2.5-coder:1.5b на промтах, подходящих для автозаполнения, показали такие результаты:
- GGUF 76.93 tokens/s
- MLX: 81.92 tokens/s
Разница в пользу MLX 6,5%. Пока явного выигрыша нет.

"Средние" модели qwen2.5-coder:14b на промтах по написанию классов/скриптов:
- GGUF: 15.05 tokens/s
- MLX: 17.59 tokens/s
Разница в пользу MLX 16.8%. Это уже похоже на распространенное мнение, что MLX модели на 10-30% быстрее GGUF.

"Тяжелые" модели qwen2.5-coder:32b на промтах по выбору архитектурных решений и реализации:
- GGUF: 2.51 tokens/s
- MLX: 5.73 tokens/s
Разница в пользу MLX в 2.28 раза. Опущу здесь момент, что скорость ниже 10 токенов в секунду уже считается слабой. Очевидно, что использовать такие модели для получения ответов в реальном времени будет некомфортно, но здесь речь идет о том, что выбор архитектурного решения или оптимальных технологий для вашего проекта всё же должно быть взвешенным, и здесь у вас есть время подождать экспертный ответ. Но факт в том, что от MLX моделей вы сможете получать его в 2 раза быстрее. 

В итоге:
- для легких моделей разница в производительности практически не будет для вас заметна, и вы можете выбирать, например, для автозаполнения ту, которая вас больше устраивает, не обращая внимание на формат GGUF или MLX и не гнаться за оптимизацией
- для средних задач профит MLX уже ощутим, и вы с большой вероятностью получите прирост скорости в 10-30%, выбрав оптимизацию, если только модель, которая её не имеет действительно не сильно лучше.
- а вот в тяжелых задачах выбор в сторону MLX однозначно стоит делать, поэтому внимательно проверяйте, какую версию модели вы скачали и запустили, чтобы ошибочно не использовать GGUF.

Надеюсь, что этот эксперимент позволил вам получить более простую и понятную картину о профите использования оптимизации MLX в ваших задачах.

Tags:
+5
Comments2

Можно ли быстро актуализировать старые PHPUnit-тесты под новые версии пакета?

Краткий ответ: да, но есть нюансы.

На Хабре незаслуженно мало статей про инструмент Rector, и даже в них совсем вскользь упоминается, что у инструмента есть отдельный функционал для актуализации PHPUnit-тестов, написанных под разные версии пакета. Причем если раньше, этот функционал был в виде отдельного пакета rector-phpunit, то на сегодня (для версии 2.6.3) этот функционал уже входит в состав основного пакета.

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

Как шло обновление:
- установили пакет rector/rector
- обновили пакет phpunit
- сделали файл конфига rector.php в котором прописали наборы правил
- запустили сначала в режиме vendor/bin/rector process --dry-run. Увидели, что аннотации @dataProvider не мигрировали в атрибуты #[DataProvider], а сами методы, на которые указывают dataProvider не стали статическими (требования PHPUint 10+).
Добавили необходимые правила в конфиг rector.php и в при первом приближении всё сработало как нужно:

<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;

return RectorConfig::configure()
    // Путь к директории с тестами
    ->withPaths([
        __DIR__ . '/tests',
    ])
    // Включаем синтаксис PHP 8.4
    ->withPhpSets(php84: true)
    // Правила берем для версии phpunit из composer.json
    ->withComposerBased(
        phpunit: true
    )
    // Общие наборы правил для улучшения качества тестов
    ->withPreparedSets(
        phpunitCodeQuality: true
    )
    // Явно запускаем встроенное правило миграции аннотаций PHPUnit в атрибуты
    ->withAttributesSets(
        phpunit: true
    );

Но и после этих инструкций не все методы dataProvider стали статическими. Основные причины были в следующем:
- использование $this в методах dataProvider
- коллизии из-за последовательности выполнения правил рефакторинга в Rector

Что помогло исправить ситуацию:
1. повторный запуск vendor/bin/rector process позволил правилам повторно пройтись по уже исправленным файлам и доделать изменения
2. использование ссылки на текущий объект в методах dataProvider плохая практика, от неё отказались

Tags:
+3
Comments0

Лучше не сохраняйте в сессии PHP объекты с защищенными или приватными свойствами, если сама сессия хранится в БД.

Оговорюсь, что не поддерживаю сохранение объектов в сессиях PHP, а пример взят из Legacy-проекта, в котором компонент рекомендованных продаж клиенту реализован в виде класса. Видимо предыдущие разработчики посчитали удобным не париться с сохранением рекомендаций в виде отдельной структуры, а сохраняли класс прямо в сессию клиента. Сами сессии хранятся в БД MySQL (тоже тема для отдельной дискуссии).

Всё это отлично работало до переезда БД на кодировку utf8mb4_general_ci. После чего начались плавающие ошибки: некоторых пользователей стало выкидывать из ПУ. Довольно быстро определили, что проблема с сессиями, чуть больше времени потребовалось, чтобы определить, что некоторые сессии внезапно становились битыми у тех клиентов, для которых срабатывал сервис подбора рекомендаций.

Немного теории. Оказалось, что PHP сохраняет свойства объектов в сессии с определенными особенностями:

  • публичные свойства `public $item` сохраняются как item

  • защищенные свойства `protected $item` сохраняются как \0*\0item

  • приватные свойства `private $item` сохраняются как \0ClassName\0item

причем \0 это нулевой байт. Главной проблемой стало то, что MySQL воспринимал этот нулевой байт как конец строки и сохранял в таблицу обрезанную строку. Сессия становилась невалидной.

Самое простое решение в данном случае изменить тип поля на BLOB, в этом случае текст корректно сохранится побайтово. По поводу вопроса, стоит ли сохранять объекты в сессию пользователя, каждый думаю решит для себя сам.

Tags:
Total votes 2: ↑2 and ↓0+4
Comments0

Функция date меняет поведение в PHP 8.x

При переносе Legacy-проекта с PHP 7.4 на 8.4 столкнулся с недокументированной проблемой изменения поведения функции date при передаче в качестве параметра timestamp значения NULL Один и тот же код даст разный результат:

echo date("Y-m-d H:i:s", null);

// PHP 7.4 и ниже 1970-01-01 00:00:00

// PHP 8.0 и выше 2026-01-14 08:11:56

В примере NULL передается в явном виде, но в рабочем коде он вполне может прилетать из БД или других переменных, поэтому потенциальная ошибка может остаться незамеченной. Вообще, по принципам ООП, явное всегда лучше неявного, да и сам я сторонник использования \DateTime. В этом случае, результат кода:

$date = new \DateTime();
$date->setTimestamp(null);
echo $date->format("Y-m-d H:i:s");

был бы одинаковый, а с версии 8.1 вы бы начали получать предупреждение

Deprecated: DateTime::setTimestamp(): Passing null to parameter #1 ($timestamp) 
of type int is deprecated
1970-01-01 00:00:00

Я бы рекомендовал перед миграцией версий PHP в Legacy-проектах либо учитывать эту особенность поведения функции date и убедиться, что NULL не приходит в параметр timestamp, либо сразу сделать рефакторинг на \DateTime, чтобы в принципе избежать таких проблем.

Tags:
Total votes 6: ↑6 and ↓0+6
Comments0

Information

Rating
1,870-th
Registered
Activity