GLiNER:本地决策与实体抽取
开发预览版。 权重已发布在 Hugging Face;Swift 模块正在审阅中,尚未包含在 speech-swift 正式版本里。
GLiNER 模块在 MLX Swift 中运行 GLiNER2.5-Decide。传入文本和允许的标签列表即可得到分类分数,也可以请求人物、时间等实体片段。
工作原理
DeBERTa 编码器同时读取文本和 schema。分类头为你的标签打分,实体头在原句中找出片段。运行时不会逐个 token 生成 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"]
)
权重
固定上游版本 7ee5da4c 的三种 MLX 转换已发布在 Hugging Face。运行时在首次使用时下载所选版本,之后复用本地缓存,全程不需要 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,机器空闲:完整请求(含分词)的中位耗时,以及进程峰值内存。三个版本在 24 个参考样例上与上游 PyTorch 模型给出相同的标签、片段和偏移,置信度差异不超过 0.006。
命令行
speech CLI 以 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、输出字段和已验证结果。
小型指令集上的准确率
16 条手写路由示例中有 12 条符合预期;8 条抽取示例中有 7 条符合。Swift 移植在 24 个参考样例上复现了上游 PyTorch 模型:token ID、标签和片段完全一致,分数差异在 0.001 以内。这些小规模集合用于检查行为和一致性,并不是全面的准确率基准。
范围与限制
- 单标签分类和实体片段;每次请求最多 512 个编码 token。
- 采用共享相对注意力的 span/count_lstm 检查点,支持 FP32、FP16 或 INT8。boundary 模型、关系图和联合约束不在此初版 API 中。
- 实体偏移使用 UTF-16,与 NSRange 一致。日期和时间需要另行规范化。
- 分数不能保证决策正确。该模块不会执行任何工具。
- 模型下载大小、进程内存和统一内存的物理占用是不同的度量。
精度与内存
FP16 把权重存储减半到 973 MB。INT8 将编码器矩阵和 token 嵌入以 64 为一组量化为 8 位,分类头、归一化和激活保持 FP16,文件为 567 MB。运行时让 INT8 矩阵保持打包状态,只解码请求用到的嵌入行。
编码器的相对位置投影只依赖权重,因此在加载时计算一次,而不是每次请求都计算。可选的 GLiNER.load(from:evaluateLayers:) 模式逐层物化编码器,以降低峰值分配。