Hosstia/AliceAI-T5-35B-A0.6B-MLX-4bit
AliceAI-T5-35B-A0.6B-MLX-4bit
MLX-quantized version of Yandex's AliceAI-T5-35B-A0.6B for Apple Silicon. This is an encoder-decoder Mixture-of-Experts (MoE) T5 translation model with 35B total parameters (0.6B active per token), optimized to run on the Metal GPU via Apple's MLX framework with fused gather_qmm MoE dispatch.
Recent fixes (2026-09)
- Fixed a 6-bit weight-packing bug: the packed width is now computed as
hidden_size * bits / 32(288 words for 6-bit) instead ofhidden_size // (32 // bits)(307), which brokemx.dequantize. - The 6-bit model was re-converted from the verified source weights with the corrected packing; expert weights verified numerically (w1 exact match, w2 within requantization noise <= 0.0023).
- Deep-tested: Q&A (2+2, capitals) and zh-ru translation prompts all pass on both 4-bit and 6-bit variants.
Model Card
Quantization Configuration
Description: affine 4-bit g64 (experts + attention)
Performance
Benchmarked on Apple M4 Pro (48 GB unified) with MLX 0.32.0.
Key Finding
The fused gather_qmm MoE dispatch eliminates 224 GPU synchronization barriers per token (one per expert per layer in the legacy flat-loop implementation). This achieves a 8.41x speedup at batch 1 and up to 16.5x at batch 8 compared to the legacy numpy-loop baseline, while maintaining full numerical parity with the reference quantization scheme.
Usage
from aliceai_mlx import load_model, generate, Translator
# Load the model directly
model = load_model("path/to/AliceAI-T5-35B-A0.6B-MLX-4bit")
# Or use the high-level Translator wrapper
translator = Translator("path/to/AliceAI-T5-35B-A0.6B-MLX-4bit")
# Simple translation (Chinese → Russian)
# min_new_tokens defaults to 0 for translation — no change needed
result = translator.translate("沈安瞠目结舌的看着包拯扬长而去。")
print(result)
# Professor mode: merge two candidate translations
result = translator.professor(zh_text, ru_teacher, ru_student)
print(result["corrected_text"])
# Batch translation for higher throughput
results = translator.complete_batch([zh_text_1, zh_text_2, zh_text_3])
# Q&A mode — ask questions in Russian
# min_new_tokens=128 prevents premature EOS truncation in quantized models
answer = translator.qa("Что такое энтропия в термодинамике?", min_new_tokens=128)
print(answer)Interactive Chat
Launch the interactive chat with Q&A, translation, correction, and professor modes:
# Start interactive chat in Q&A mode
python chat.py --model 4bit --task qa
# Available task modes: translate, correct, professor, qa, raw
# Supports multi-turn conversation history, slash commands, and stream cleanupSlash commands: /task, /model, /temp, /tokens, /min, /clear, /info, /help, /quit.
Runtime code included: This repository contains thealiceai_mlxPython package,chat.py,requirements.txt, andARTICLE.md(a detailed technical article about the conversion process). Clone the repo and runpip install -r requirements.txt, thenpython chat.py --model .to start the interactive chat.
min_new_tokens Parameter
The min_new_tokens parameter suppresses the EOS (end-of-sequence) logit for the first N generated tokens, preventing premature truncation that occurs in quantized models. This is especially important for Q&A mode, where answers can be cut off mid-sentence without it.
- Translation mode:
min_new_tokens=0(default) — translation produces concise output and does not need forced continuation. - Q&A mode:
min_new_tokens=128(default) — ensures answers are complete and not truncated mid-sentence.
Known Limitations
- 6-bit variant has lower Q&A quality than 4-bit: answers tend to be shorter and exhibit more repetition.
- `min_new_tokens` is required for Q&A mode — without it, quantized models emit EOS prematurely and answers truncate mid-sentence.
- Translation mode may truncate on longer inputs in quantized variants; consider splitting very long source texts into shorter segments.
- Chinese-language Q&A output is unreliable — quantized models cannot reliably generate Chinese text in Q&A mode. The 6-bit model degenerates into empty marker loops; the 4-bit model produces garbled characters. The model is primarily trained for Chinese→Russian translation, not multilingual Q&A. Russian Q&A works well.
Changelog
- Added `min_new_tokens` parameter to
generate_step(),generate(),complete(),complete_batch(), andstream()— suppresses EOS logit for the first N tokens to prevent premature truncation in quantized models. Default 128 for Q&A mode, 0 for translation. - Added Q&A mode with
parse_qa_answer()cleanup — strips format-spec markers, echoes of the prompt format, repeated answer blocks, and trailing noise from the model output. - Added interactive chat (
chat.py) with 5 task modes (translate, correct, professor, qa, raw), multi-turn conversation history for Q&A, slash commands (/task,/model,/temp,/tokens,/min,/clear,/info,/help,/quit), and stream cleanup. - Added repetition cutting via
_cut_repetition()inparse_qa_answer()andparse_corrected()— detects and cuts repeated answer blocks that quantized models produce aftermin_new_tokensforces continued generation. - Added stream cleanup for Q&A mode — stream output is buffered and cleaned via
parse_qa_answer()before display; other modes use raw streaming for low latency. - Fixed format-spec echo handling in `parse_qa_answer()` — when
min_new_tokensforces the model to continue past its natural answer, quantized models may echo the format-spec template text (e.g.- **Ответ**: [Подробный развёрнутый ответ на вопрос]) instead of writing real content. Such echoes are now stripped anywhere in the output and are no longer mistaken for repetition markers; dangling trailing markers (e.g. a bare**Объяснение:**at the end) are removed as well. - Fixed question-echo handling in `_cut_repetition()` — the 4-bit model sometimes echoes the user's question verbatim before giving the real answer, separated by a `
Ответ: marker. The parser now detects this (text before the marker ends with ?) and discards the question echo, keeping only the real answer. The repetition-cut loop was restructured from finditer to a while/search` loop to avoid stale match positions after text reassignment.
- Added consecutive-duplicate-line deduplication in
_cut_repetition()— the 6-bit model may repeat the same line (e.g.**Reason**: ...) multiple times in a row; only the first copy of each run is kept. - Extended `_TRAILING_MARKER_RE` to match English marker words (
Reason,Alternative,Explanation,Consequences,Answer) in addition to Russian ones, so dangling trailing markers are stripped in both languages. - Removed language constraint from `QA_PROMPT` — the prompt previously forced Russian answers for Chinese-related questions, conflicting with user requests for answers in other languages. The prompt now instructs the model to answer in the language of the question or as requested by the user.
- Extended `_TRAILING_MARKER_RE` for language-specific headers — the model may write section headers like
### **Ответ на китайском языке**:but never fill in the content. The regex now matchesОтвет на <language> языкеpatterns (with optional#+markdown heading prefix) so such dangling headers are stripped. - Extended `_ANSWER_RE` to match English `Answer` — the leading answer marker stripper now handles both Russian
Ответand EnglishAnswer, so- Answer: [text]markers are stripped correctly. - Added Q&A fallback message — when the model degenerates into empty answer markers (e.g. 28+ bare
- Ответ:lines with no content),parse_qa_answer()now returns a clear fallback message (QA_FALLBACK_MESSAGE) instead of an empty string.chat.pydisplays this message instead of a blank response, and failed answers are no longer added to the conversation history. - Smart repetition cut keeps the best answer block —
_cut_repetition()Rule 1 now splits the output into blocks at real repetition markers (skipping format-spec echoes), discards question-echo blocks (ending with?), strips leading answer markers from each block, and keeps the longest non-question block (preferring the earliest on ties). This fixes the 4-bit model's tendency to produce a short first answer followed by a better, longer one after a repetition marker. - Stripped `<SPAN#N>` tokens from all outputs — the model may emit span tokens like
<SPAN#135>in its output. These are now stripped by_SPAN_TOKEN_REin_decode_output(),stream(), andparse_qa_answer(), so they never appear in the final text. - Stripped question echoes from Q&A output — added
_QUESTION_ECHO_REto detect and remove**Вопрос**:/**Question**:echoes that the prompt template may cause the model to reproduce. The echo is stripped from the marker to the end of the text. - Added history quality guard in `chat.py` — answers shorter than 20 characters, fallback messages, and bracket-only markers are no longer added to the conversation history, preventing poisoned context from degrading subsequent Q&A turns.
- Fixed trailing markers in translation mode — when the model skips the
**Исправленный перевод**:marker (common for short translations) and outputs the translation directly followed by `
Ответ:, translate() now falls back to parseqaanswer()` to strip trailing markers instead of returning raw output.
- Fixed bare `[Ответ]` bracket marker leak in Q&A mode — the 6-bit model in multi-turn Q&A could degenerate to outputting only
[Ответ](the format-spec placeholder with the word "Ответ" instead of real content) after several turns of fabricated answers. Added_BRACKET_MARKER_REto strip[Ответ]/[Answer]anywhere in the output before and after_cut_repetition(). Updated_ANSWER_REand_REPETITION_ANSWER_REwith strict alternation(?:\[\s*(?:Ответ|Answer)\s*\]|(?:Ответ|Answer))to match bracket markers exactly without false positives on[Ответ на вопрос 1]-style references. Updated_TRAILING_MARKER_REwith optional brackets. - Limited conversation history to 2 turns in
chat.py(_MAX_HISTORY_TURNS = 2) — when the model hallucinates in early Q&A turns, fabricated answers accumulate in the history and cause progressive degeneration in later turns. Limiting history to the last 2 turns prevents this poisoning while still providing conversation context.
Phase 29 — LM head optimization (2.2× decode speedup)
- Problem: The tied LM head classifier (135040×1536) consumed 68% of decode-step time because
weight.astype(float32)rebuilt a 792 MB tensor on every token. - Fix 1: Cache the float32 cast — bit-identical to per-step casting, 1.7× speedup.
- Fix 2: Custom Metal matvec kernel (
FastLMHead) reads fp16 weights and accumulates in float32, halving bandwidth (396 MB vs 792 MB per token). Self-validates againstmx.matmulbefore installation; falls back to cached-castmx.matmulif unavailable. - Fix 3: Corrected causal mask for multi-token decode (was square
[tgt, tgt], now[tgt, offset+tgt]to account for KV cache). - Result: 6-bit batch-1 throughput 73.6 → 159.9 tok/s (2.17×), 4-bit batch-1 72.7 → 158.9 tok/s (2.19×). All greedy outputs bit-identical (10/10 paragraphs).
- New files:
lm_head.py(Metal kernel),profile_decode.py(ablation profiler),test_lm_head.py(exactness test).
Requirements
- MLX 0.32.0 or later
- Apple Silicon (M1, M2, M3, M4 family)
- macOS 14.0 (Sonoma) or later
- Unified memory: ≥19 GB recommended
- Python 3.10+
transformers(for the tokenizer)huggingface_hub(for automatic download)
License
This model is released under the same license as the original `yandex/AliceAI-T5-35B-A0.6B` model. Please refer to the original model card for license details.
Citation / Credit
The original model was created and trained by Yandex. This repository contains only the MLX-quantized weights and the inference runtime. If you use this model, please cite the original work:
@misc{yandex-aliceai-t5,
author = {Yandex},
title = {AliceAI-T5-35B-A0.6B},
year = {2025},
url = {https://huggingface.co/yandex/AliceAI-T5-35B-A0.6B},
}Русская версия
MLX-квантованная версия AliceAI-T5-35B-A0.6B от Яндекса для Apple Silicon. Это encoder-decoder модель перевода с архитектурой Mixture-of-Experts (MoE) T5, имеющая 35B всего параметров (0.6B активных на токен), оптимизированная для работы на Metal GPU через фреймворк MLX от Apple с использованием слитой диспетчеризации MoE gather_qmm.
Последние исправления (2026-09)
- Исправлена ошибка упаковки 6-битных весов: ширина упакованного тензора теперь вычисляется как
hidden_size * bits / 32(288 слов для 6 бит) вместоhidden_size // (32 // bits)(307), что ломалоmx.dequantize. - 6-битная модель переконвертирована из проверенных исходных весов с исправленной упаковкой; экспертные веса проверены численно (w1 — точное совпадение, w2 — в пределах шума реквантизации <= 0.0023).
- Глубокое тестирование пройдено: Q&A (2+2, столицы) и переводы zh-ru корректны на обеих вариантах, 4-битном и 6-битном.
Карточка модели
Конфигурация квантования
Описание: affine 4-bit g64 (experts + attention)
Производительность
Тестирование на Apple M4 Pro (48 GB unified) с MLX 0.32.0.
Ключевой результат
Слитая диспетчеризация MoE gather_qmm устраняет 224 барьера синхронизации GPU на токен (по одному на каждый эксперт на каждый слой в устаревшей реализации с плоским циклом). Это обеспечивает ускорение в 8.41x при batch 1 и до 16.5x при batch 8 по сравнению с базовым вариантом на numpy-циклах, сохраняя полное численное соответствие с эталонной схемой квантования.
Использование
from aliceai_mlx import load_model, generate, Translator
# Загрузка модели напрямую
model = load_model("path/to/AliceAI-T5-35B-A0.6B-MLX-4bit")
# Или высокоуровневая обёртка Translator
translator = Translator("path/to/AliceAI-T5-35B-A0.6B-MLX-4bit")
# Простой перевод (китайский → русский)
# min_new_tokens по умолчанию 0 для перевода — изменять не нужно
result = translator.translate("沈安瞠目结舌的看着包拯扬长而去。")
print(result)
# Режим профессора: объединение двух вариантов перевода
result = translator.professor(zh_text, ru_teacher, ru_student)
print(result["corrected_text"])
# Пакетный перевод для повышения пропускной способности
results = translator.complete_batch([zh_text_1, zh_text_2, zh_text_3])
# Режим вопросов и ответов — задавайте вопросы на русском
# min_new_tokens=128 предотвращает преждевременную обрезку в квантованных моделях
answer = translator.qa("Что такое энтропия в термодинамике?", min_new_tokens=128)
print(answer)Интерактивный чат
Запуск интерактивного чата с режимами Q&A, перевода, коррекции и профессора:
# Запуск интерактивного чата в режиме Q&A
python chat.py --model 4bit --task qa
# Доступные режимы: translate, correct, professor, qa, raw
# Поддержка многораундовой истории диалога, слэш-команд и очистки потокаСлэш-команды: /task, /model, /temp, /tokens, /min, /clear, /info, /help, /quit.
Код выполнения включён: Этот репозиторий содержит Python-пакетaliceai_mlx,chat.py,requirements.txtиARTICLE.md(подробная техническая статья о процессе конвертации). Клонируйте репозиторий и выполнитеpip install -r requirements.txt, затемpython chat.py --model .для запуска интерактивного чата.
Параметр min_new_tokens
Параметр min_new_tokens подавляет логит EOS (конец последовательности) для первых N сгенерированных токенов, предотвращая преждевременную обрезку, которая возникает в квантованных моделях. Это особенно важно для режима Q&A, где ответы могут обрываться на середине предложения без этого параметра.
- Режим перевода:
min_new_tokens=0(по умолчанию) — перевод даёт лаконичный результат и не требует принудительного продолжения. - Режим Q&A:
min_new_tokens=128(по умолчанию) — гарантирует, что ответы будут полными и не обрежутся на середине предложения.
Известные ограничения
- 6-битный вариант имеет более низкое качество Q&A, чем 4-битный: ответы склонны быть короче и содержать больше повторов.
- `min_new_tokens` обязателен для режима Q&A — без него квантованные модели преждевременно генерируют EOS, и ответы обрываются на середине предложения.
- Режим перевода может обрезать длинные входные тексты в квантованных вариантах; рекомендуется разбивать очень длинные исходные тексты на более короткие сегменты.
- Ответы на китайском языке в режиме Q&A ненадёжны — квантованные модели не могут надёжно генерировать китайский текст в режиме Q&A. 6-битная модель деградирует в пустые циклы маркеров; 4-битная модель выдаёт искажённые символы. Модель в первую очередь обучена для перевода китайский→русский, а не для многоязычного Q&A. Q&A на русском работает корректно.
История изменений
- Добавлен параметр `min_new_tokens` в
generate_step(),generate(),complete(),complete_batch()иstream()— подавляет логит EOS для первых N токенов, предотвращая преждевременную обрезку в квантованных моделях. По умолчанию 128 для режима Q&A, 0 для перевода. - Добавлен режим Q&A с очисткой через
parse_qa_answer()— удаляет маркеры формата, эхо промпта, повторяющиеся блоки ответов и завершающий шум из вывода модели. - Добавлен интерактивный чат (
chat.py) с 5 режимами (translate, correct, professor, qa, raw), многораундовой историей диалога для Q&A, слэш-командами (/task,/model,/temp,/tokens,/min,/clear,/info,/help,/quit) и очисткой потока. - Добавлена обрезка повторов через
_cut_repetition()вparse_qa_answer()иparse_corrected()— обнаруживает и удаляет повторяющиеся блоки ответов, которые квантованные модели генерируют после принудительного продолжения черезmin_new_tokens. - Добавлена очистка потока для режима Q&A — потоковый вывод буферизуется и очищается через
parse_qa_answer()перед отображением; остальные режимы используют прямую потоковую передачу для минимальной задержки. - Исправлена обработка эхо формата в `parse_qa_answer()` — когда
min_new_tokensзаставляет модель продолжать после естественного конца ответа, квантованные модели могут повторять текст шаблона формата (например,- **Ответ**: [Подробный развёрнутый ответ на вопрос]) вместо реального содержимого. Такие эхо теперь удаляются в любом месте вывода и не принимаются за маркеры повторов; висячие завершающие маркеры (например, одиночный**Объяснение:**в конце) также удаляются. - Исправлена обработка эхо вопроса в `_cut_repetition()` — 4-битная модель иногда дословно повторяет вопрос пользователя перед ответом, отделяя его маркером `
Ответ: . Парсер теперь обнаруживает это (текст перед маркером заканчивается на ?) и отбрасывает эхо вопроса, оставляя только реальный ответ. Цикл обрезки повторов переписан с finditer на цикл while/search` во избежание устаревших позиций совпадений после переназначения текста.
- Добавлено удаление подряд идущих дубликатов строк в
_cut_repetition()— 6-битная модель может повторять одну и ту же строку (например,**Reason**: ...) несколько раз подряд; сохраняется только первая копия в каждой серии. - Расширен `_TRAILING_MARKER_RE` для сопоставления английских маркерных слов (
Reason,Alternative,Explanation,Consequences,Answer) в дополнение к русским, так что висячие завершающие маркеры удаляются на обоих языках. - Удалено ограничение языка из `QA_PROMPT` — промпт ранее принуждал модель отвечать по-русски на вопросы, связанные с китайским языком, что конфликтовало с запросами пользователя на других языках. Теперь промпт указывает модели отвечать на языке вопроса или на запрошенном языке.
- Расширен `_TRAILING_MARKER_RE` для языковых заголовков — модель может писать заголовки разделов вроде
### **Ответ на китайском языке**:, но не заполнять содержимое. Регулярное выражение теперь сопоставляет шаблоныОтвет на <язык> языке(с опциональным префиксом заголовка#+), так что такие висячие заголовки удаляются. - Расширен `_ANSWER_RE` для сопоставления английского `Answer` — удаление ведущего маркера ответа теперь обрабатывает как русское
Ответ, так и английскоеAnswer, так что маркеры- Answer: [текст]корректно удаляются. - Добавлено резервное сообщение в Q&A — когда модель вырождается в пустые маркеры ответа (например, 28+ пустых строк
- Ответ:без содержимого),parse_qa_answer()теперь возвращает понятное резервное сообщение (QA_FALLBACK_MESSAGE) вместо пустой строки.chat.pyпоказывает это сообщение вместо пустого ответа, а неудачные ответы больше не попадают в историю диалога. - Умная обрезка повторов сохраняет лучший блок ответа — правило 1
_cut_repetition()теперь разбивает вывод на блоки по реальным маркерам повторов (пропуская эхо формата), отбрасывает блоки-эхо вопросов (заканчивающиеся на?), удаляет ведущие маркеры ответа из каждого блока и сохраняет самый длинный блок без эха вопроса (при равенстве — самый ранний). Это исправляет склонность 4-битной модели выдавать короткий первый ответ, за которым после маркера повтора следует более полный. - Удалены токены `<SPAN#N>` из всех выводов — модель может выдавать span-токены вроде
<SPAN#135>в своём выводе. Теперь они удаляются регулярным выражением_SPAN_TOKEN_REв_decode_output(),stream()иparse_qa_answer(), так что никогда не появляются в итоговом тексте. - Удалены эхо вопросов из вывода Q&A — добавлено
_QUESTION_ECHO_REдля обнаружения и удаления эхо**Вопрос**:/**Question**:, которые шаблон промпта может заставить модель воспроизвести. Эхо удаляется от маркера до конца текста. - Добавлен контроль качества истории в `chat.py` — ответы короче 20 символов, резервные сообщения и маркеры из одних скобок больше не попадают в историю диалога, что предотвращает отравление контекста и деградацию последующих раундов Q&A.
- Исправлены висячие маркеры в режиме перевода — когда модель пропускает маркер
**Исправленный перевод**:(частое явление для коротких переводов) и выводит перевод напрямую, после которого следует `
Ответ:, метод translate() теперь использует parseqaanswer()` для удаления висячих маркеров вместо возврата необработанного вывода.
- Исправлена утечка маркера `[Ответ]` в квадратных скобках в режиме Q&A — 6-битная модель в многораундовом Q&A могла вырождаться в вывод только
[Ответ](плейсхолдер формата со словом "Ответ" вместо реального содержимого) после нескольких раундов сфабрикованных ответов. Добавлено регулярное выражение_BRACKET_MARKER_REдля удаления[Ответ]/[Answer]в любом месте вывода до и после_cut_repetition(). Обновлены_ANSWER_REи_REPETITION_ANSWER_REстрогой альтернацией(?:\[\s*(?:Ответ|Answer)\s*\]|(?:Ответ|Answer))для точного сопоставления маркеров в скобках без ложных срабатываний на ссылки вида[Ответ на вопрос 1]. Обновлён_TRAILING_MARKER_REопциональными скобками. - Ограничение истории диалога до 2 раундов в
chat.py(_MAX_HISTORY_TURNS = 2) — когда модель галлюцинирует в ранних раундах Q&A, сфабрикованные ответы накапливаются в истории и вызывают прогрессирующую деградацию в последующих раундах. Ограничение истории последними 2 раундами предотвращает это отравление, сохраняя при этом контекст диалога.
Фаза 29 — Оптимизация LM head (ускорение декодирования в 2.2×)
- Проблема: Связанный классификатор LM head (135040×1536) занимал 68% времени шага декодирования, так как
weight.astype(float32)перестраивал тензор размером 792 МБ на каждый токен. - Исправление 1: Кэширование приведения к float32 — побитово идентично приведению на каждом шаге, ускорение в 1.7×.
- Исправление 2: Пользовательское Metal-ядро матрично-векторного умножения (
FastLMHead) читает веса в fp16 и накапливает в float32, сокращая пропускную способность вдвое (396 МБ против 792 МБ на токен). Самопроверка черезmx.matmulперед установкой; откат к кэшированномуmx.matmul, если ядро недоступно. - Исправление 3: Исправлена причинная маска для многосимвольного декодирования (была квадратной
[tgt, tgt], теперь[tgt, offset+tgt]для учёта KV-кэша). - Результат: Пропускная способность 6-bit batch-1 73.6 → 159.9 ток/с (2.17×), 4-bit batch-1 72.7 → 158.9 ток/с (2.19×). Все жадные выводы побитово идентичны (10/10 абзацев).
- Новые файлы:
lm_head.py(Metal-ядро),profile_decode.py(профайлер абляции),test_lm_head.py(тест точности).
Системные требования
- MLX 0.32.0 или новее
- Apple Silicon (M1, M2, M3, M4)
- macOS 14.0 (Sonoma) или новее
- Единая память: ≥19 ГБ рекомендуется
- Python 3.10+
transformers(для токенизатора)huggingface_hub(для автоматической загрузки)
Лицензия
Эта модель распространяется под той же лицензией, что и исходная модель `yandex/AliceAI-T5-35B-A0.6B`. Подробности лицензии см. в карточке оригинальной модели.
Благодарности / Цитирование
Оригинальная модель создана и обучена компанией Яндекс. Этот репозиторий содержит только MLX-квантованные веса и среду выполнения. При использовании этой модели, пожалуйста, цитируйте оригинальную работу:
@misc{yandex-aliceai-t5,
author = {Yandex},
title = {AliceAI-T5-35B-A0.6B},
year = {2025},
url = {https://huggingface.co/yandex/AliceAI-T5-35B-A0.6B},
}