惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
G
Google Developers Blog
aimingoo的专栏
aimingoo的专栏
罗磊的独立博客
博客园 - 【当耐特】
M
MIT News - Artificial intelligence
D
Docker
博客园 - 三生石上(FineUI控件)
博客园 - 司徒正美
人人都是产品经理
人人都是产品经理
博客园 - 叶小钗
月光博客
月光博客
S
SegmentFault 最新的问题
Jina AI
Jina AI
Blog — PlanetScale
Blog — PlanetScale
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - Franky
L
LangChain Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Microsoft Azure Blog
Microsoft Azure Blog
阮一峰的网络日志
阮一峰的网络日志
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Last Week in AI
Last Week in AI

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания
Как я добавил llama.cpp бэкенд в CosyVoice3 и ускорил инф...
Ferraro · 2026-04-26 · via Все публикации подряд на Хабре

Уровень сложностиСредний

Время на прочтение3 мин

Охват и читатели107

Туториал

CosyVoice3 — одна из лучших open source TTS моделей прямо сейчас, особенно для русского языка. Но у неё есть проблема: LLM-часть на PyTorch работает медленно на слабых GPU вроде T4. RTF (real-time factor) около 1.17 — это значит синтез одной секунды аудио занимает больше секунды реального времени.

Я решил это исправить, добавив поддержку llama.cpp через llama-cpp-python. Результат: RTF упал до ~0.45, то есть ускорение примерно в 2.6x.

В этой статье расскажу как это работает, почему это нетривиально, и как попробовать самому.


Почему CosyVoice LLM — не обычная LLM

CosyVoice3 использует LLM (на базе Qwen2.5-0.5B) для генерации речевых токенов. Но это не стандартная языковая модель — у неё две головы и два набора эмбеддингов:

  • Текстовые эмбеддинги (embed_tokens) — стандартный словарь Qwen, ~151936 токенов

  • Речевые эмбеддинги (speech_embedding) — 6561 токен для аудио

  • Речевая голова (llm_decoder) — отдельный выходной слой для речевых токенов

llama.cpp не знает об этой архитектуре. Он ожидает стандартную модель с одним словарём и одной lm_head.


Конвертер: объединяем всё в одну обычную LLM

Чтобы скормить модель llama.cpp, нужно привести её к стандартному виду. Идея простая: слить оба эмбеддинга в один большой словарь.

# Конкатенируем текстовые и речевые эмбеддинги
input_emb = torch.cat([txt_emb, spk_in], dim=0)  
# Теперь vocab_size = 151936 + 6561+200 = ~158700

# Собираем единую lm_head
full_output = torch.zeros((input_emb.shape[0], input_emb.shape[1]))
full_output[:151936, :] = txt_emb        # текстовая часть
full_output[151936:, :] = spk_out        # речевая часть

После этого обновляем config.json (новый vocab_size, tie_word_embeddings: false) и расширяем vocab.json, добавляя токены вида <|s_0|>, <|s_1|>, ... для речевых токенов.

Теперь convert_hf_to_gguf.py из llama.cpp работает без изменений и видит просто большой Qwen2.5.

Готовые сконвертированные модели опубликованы на HuggingFace: Ferraronp/CosyVoice3-qwen2.5-0.5b-speech-gguf

Доступные варианты квантизации: Q2_K, Q3_K_S, Q3_K_M, Q3_K_L, Q4_0, Q4_1, Q4_K_S, Q4_K_M, Q5_0, Q5_1, Q5_K_S, Q5_K_M, Q6_K, Q8_0, BF16, F16, F32.

Конвертер (Colab-ноутбук): Ferraronp/CosyVoice-gguf-converter


Инференс: как не дать модели генерировать текст вместо речи

После конвертации возникает другая проблема. Модель теперь видит огромный словарь из текстовых и речевых токенов. Ничто не мешает ей на выходе генерировать обычный текст — ведь с её точки зрения это просто токены с маленькими индексами.

Решение: маскировка логитов при сэмплинге. Перед выбором следующего токена берём сырые логиты из llama.cpp, ставим -inf на все позиции кроме речевых токенов и EOS:

logits = np.array(self.llm_gguf.scores[logit_pos], dtype=np.float32)

# Разрешаем только речевые токены [151936, 151936+6561) и EOS
valid = np.full(n_vocab, False)
valid[speech_offset : speech_offset + base_speech_size] = True
valid[eos_token_id] = True
logits[~valid] = -np.inf

# Дальше стандартный softmax + top-k/top-p сэмплинг
probs = np.exp((logits - logits[valid].max()) / temperature)
probs /= probs.sum()
next_token = np.random.choice(n_vocab, p=probs)

Встроенный sample() из llama-cpp-python тоже работает, но иногда может вернуть текстовый токен — в этом случае код автоматически переключается на маскировку.


А как насчёт TRT-LLM?

Существует форк FastCosyVoice с поддержкой TensorRT-LLM. Это мощный инструмент, но он требует Docker и конвертацию модели под конкретную GPU. Бенчмарки там только на RTX 3090 и RTX 5060ti. На слабых картах это либо не заведётся, либо потребует часов настройки.

llama-cpp-python бэкенд устанавливается одной командой:

pip install llama-cpp-python

Никакого Docker, никакого Triton, никакой конвертации под GPU. Работает на слабых GPU, работает на CPU. Если у вас нет топовой карты — это ваш вариант.


Результаты

Тестировалось на NVIDIA T4, fp16:

Бэкенд

Среднее RTF

PyTorch fp16 (оригинал)

~1.17

llama-cpp-python F16 GGUF

~0.45

RTF < 1.0 означает что синтез идёт быстрее реального времени — можно использовать в стриминге без накопления лага.


Как попробовать

Установка:

pip install llama-cpp-python

Использование:

from cosyvoice.cli.cosyvoice import AutoModel

cosyvoice = AutoModel(
    model_dir='pretrained_models/Fun-CosyVoice3-0.5B',
    load_llama_cpp=True,
    gguf_model_path='/path/to/cosyvoice_llm_f16.gguf'
)

# Все стандартные методы работают как обычно
for output in cosyvoice.inference_zero_shot(text, prompt_text, prompt_wav):
    audio = output['tts_speech']

Скачать готовую GGUF модель: HuggingFace

Форк с llama-cpp-python бэкендом (для быстрого старта): Ferraronp/CosyVoice

PR в оригинальный репозиторий: FunAudioLLM/CosyVoice#1872