GLiNER: локальные решения и извлечение сущностей
Предварительная версия. Веса опубликованы на Hugging Face; модуль Swift на ревью и пока не вошёл в релиз speech-swift.
Модуль GLiNER запускает GLiNER2.5-Decide на MLX Swift. Передайте текст и список допустимых меток, чтобы получить оценки классификации, или запросите фрагменты сущностей, например человека и время.
Как это работает
Энкодер DeBERTa читает текст и схему вместе. Классификационные головы оценивают ваши метки. Головы сущностей находят фрагменты исходного предложения. Рантайм не генерирует JSON-ответ токен за токеном.
import GLiNER
let model = try await GLiNER.fromPretrained()
let choices = try model.classify(
"Remind me to call Dad at six PM.",
labels: ["create_reminder", "send_message", "other"]
)
let spans = try model.extractEntities(
"Remind me to call Dad at six PM.",
labels: ["person", "time"]
)
Веса
На Hugging Face опубликованы три MLX-конвертации зафиксированной ревизии 7ee5da4c. Рантайм скачивает выбранный вариант при первом использовании и дальше берёт его из локального кэша; Python не нужен.
| Вариант | Репозиторий | Веса | Маршрутизация | Извлечение | Пиковая память |
|---|---|---|---|---|---|
int8 (по умолчанию) | aufklarer/GLiNER2.5-Decide-340M-MLX-8bit | 567 MB | 7.6 ms | 8.9 ms | 0.85 GB |
fp16 | aufklarer/GLiNER2.5-Decide-340M-MLX-fp16 | 973 MB | 8.8 ms | 10.0 ms | 1.58 GB |
fp32 | aufklarer/GLiNER2.5-Decide-340M-MLX | 1.95 GB | 11.1 ms | 12.6 ms | 2.55 GB |
Apple M5 Pro, без другой нагрузки: медиана полного запроса с токенизацией и пиковая память процесса. Все три варианта возвращают те же метки, фрагменты и смещения, что и исходная модель PyTorch, на 24 эталонных примерах; расхождение уверенности не больше 0,006.
Командная строка
CLI speech предоставляет обе задачи как speech gliner classify и speech gliner extract. Метки передаются через запятую, --description label=text можно повторять. Без текста ввод читается из stdin. --variant выбирает int8 (по умолчанию), fp16 или fp32, а --model-dir загружает локальный пакет вместо скачивания. Неверные аргументы отклоняются до загрузки модели. С --json вывод содержит вероятность каждой метки или фрагменты со смещениями UTF-16, а также время загрузки и инференса.
swift build -c release --product speech --disable-sandbox
scripts/build_mlx_metallib.sh release
.build/release/speech gliner classify "Remind me to call Dad at six PM." \
--labels create_reminder,send_message,set_timer,other
.build/release/speech gliner extract "Remind me to call Dad at six PM." \
--labels person,time --json
В карточке модели для агентов (файл Markdown) описаны точный API, поля вывода и проверенные результаты.
Точность на небольшом наборе команд
Из шестнадцати написанных вручную примеров маршрутизации ожиданиям соответствовали 12; а из восьми примеров извлечения 7. Порт на Swift воспроизводит исходную модель PyTorch на 24 эталонных примерах: те же ID токенов, метки и фрагменты, оценки в пределах 0,001. Эти небольшие наборы проверяют поведение и точность воспроизведения; это не широкий бенчмарк точности.
Возможности и ограничения
- Классификация с одной меткой и фрагменты сущностей; до 512 закодированных токенов на запрос.
- Чекпоинты span/count_lstm с общим относительным вниманием, в FP32, FP16 или INT8. Модели boundary, графы отношений и совместные ограничения не входят в этот первый API.
- Смещения сущностей в UTF-16, как у NSRange. Даты и время нужно нормализовать отдельно.
- Оценка не гарантирует, что решение верное. Модуль не выполняет никаких инструментов.
- Размер загрузки, память процесса и физический объём в единой памяти измеряются по-разному.
Точность вычислений и память
FP16 вдвое сокращает хранение весов, до 973 МБ. INT8 квантует матрицы энкодера и эмбеддинги токенов до 8 бит группами по 64, а головы, нормализация и активации остаются в FP16; файл весит 567 МБ. Рантайм держит матрицы INT8 упакованными и декодирует только те строки эмбеддингов, которые нужны запросу.
Проекции относительных позиций в энкодере зависят только от весов, поэтому вычисляются один раз при загрузке, а не при каждом запросе. Необязательный режим GLiNER.load(from:evaluateLayers:) вычисляет слои энкодера по одному, чтобы снизить пиковые выделения памяти.