这个模型是孟加拉语 NER 的实用化部署产物。它源自 google/muril-large-cased
在 SampurNER 孟加拉语语料上的微调,能把一句孟加拉语拆成词级标签,识别出人名、
地名、机构、设施、事件、艺术类作品等 133 种 IOB2 实体。为了让它在昇腾 910
NPU 上跑起来,我们走了 vLLM-Ascend 的 token_classify 池化路线,最终对外暴露
一个标准的 OpenAI 风格 HTTP 接口,调用方只需发一个 POST 请求即可拿到逐 token
的实体标签。
技术上它就是一个标准的 BERT-large encoder:24 层、1024 维隐层、16 头注意力、
约 5.9 亿参数、WordPiece 词表 19.7 万。因为 vLLM 本身就注册了
BertForTokenClassification,且 vllm-ascend 已经带上了 BERT 的 worker 补丁,
整个适配过程不需要改动任何推理框架源码。
适配与验证都在一台昇腾 910 设备上完成,关键版本如下:
tensor-parallel-size 1推理服务占用 chip1(逻辑卡 13),通过 ASCEND_RT_VISIBLE_DEVICES=1 隔离,
避免与同机其他适配任务抢占资源。
把模型权重放到本地目录后,用下面这条命令把服务拉起来:
export ASCEND_RT_VISIBLE_DEVICES=1
vllm serve /opt/atomgit/models/sampurner_20260823 \
--load-format safetensors \
--dtype bfloat16 \
--max-model-len 512 \
--max-num-seqs 8 \
--port 8095 --host 127.0.0.1 \
--enforce-eager --runner pooling \
--tensor-parallel-size 1 \
--gpu-memory-utilization 0.1 \
--served-model-name sampurner \
--trust-remote-code \
--no-enable-prefix-caching \
--no-enable-chunked-prefill服务正常起来后,日志里会出现 Supported tasks: ['token_classify'] 和
Starting vLLM server on http://127.0.0.1:8095 两行关键信息,看到它们就说明
引擎已经就绪。
先确认服务在听:
curl -sf http://127.0.0.1:8095/v1/models然后发一条推理请求,记得在请求体里带上任务类型:
curl -s http://127.0.0.1:8095/pooling \
-H 'Content-Type: application/json' \
-d '{"model":"sampurner","input":"ঢাকায় আগুন লাগলে মানুষ ক্ষতিগ্রস্ত হয়","task":"token_classify"}'返回体里 data[0].data 是一个二维数组,行数等于 token 数,每行是 133 个
类别的概率分布。用仓库里的 inference.py 可以直接看到解析后的实体:
python3 inference.py --text "ঢাকায় আগুন লাগলে মানুষ ক্ষতিগ্রস্ত হয়"输出类似这样——"ঢাকায়" 被标成地名,其余词都是 O:
ঢাকায় -> B-location-GPE
আগুন -> O
...
[实体] ঢাকায় => location-GPE用 8 个并发线程压测,服务能稳定吃到 137 req/s 左右;单条短句的响应时间基本
在 25ms 上下。拿 502 个 token 的长文本对比 CPU 与 NPU:CPU 上 fp32 推理要
5 秒多,NPU 上 bf16 只要 75ms,提速接近 70 倍。推理期间 npu-smi 看到
chip1 的 AICore 在 11% 左右,HBM 占用约 4.2GB——对一个大 encoder 来说很轻量。
手工挑了 4 句有代表性的孟加拉语,覆盖地名、人名、机构名,逐词核对结果:
ঢাকায় আগুন লাগলে মানুষ ক্ষতিগ্রস্ত হয় → 识别出地名 ঢাকায়রবীন্দ্রনাথ ঠাকুর কলকাতায় জন্মগ্রহণ করেন → 人名 রবীন্দ্রনাথ ঠাকুর、地名 কলকাতায়টাটা মোটরস ঢাকায় নতুন শাখা খুলেছে → 机构 টাটা মোটরস、地名 ঢাকায়আগরতলায় বিক্ষোভে অন্তত ১০ জন আহত হয়েছেন → 地名 আগরতলায়四句全部命中。因为走的是 argmax + eval 模式,同一句话重复请求输出完全一致, 结果可复现。
实践里踩过的几个坑,列出来供参考:
"task":"token_classify"——光在启动参数里指定 --runner pooling
是不够的。--dtype 只认 bfloat16/float32,传 bf16 会直接报参数错误。ASCEND_RT_VISIBLE_DEVICES
指定空闲卡,别去动别人的进程。--no-enable-chunked-prefill,否则行为不符合预期。