货运物流里的实体识别不是普通 NER。提单、航班、机场、ULD、商品描述、客户备注经常混着英文缩写、本地语言、行业黑话和不完整句子。来源文章分享了 IBS Software 使用 Amazon Bedrock 知识蒸馏能力构建双语货运 NER 的技术路线:用更强的教师模型生成 token 级标注,再训练更轻、更稳定、成本更可控的学生模型。
这类方案的价值不在于“让大模型直接上线”,而在于把大模型的理解能力压缩到一个适合生产环境的 NER 组件里。
为什么货运 NER 适合做蒸馏
货运系统中的文本通常短、密、噪声大。例如:
2 PCS pharma shipment to FRA, temp 2-8CULD AKE12345EK offload at DXB请安排明早飞往新加坡的冷链货物,重量 120kg
业务需要识别的不只是人名、地点这类通用实体,还包括:
- 航站、机场、航司、航班号
- 货物类型、温控条件、危险品标识
- 重量、件数、体积、ULD 编号
- 操作动作,如 offload、hold、rebook、release
- 中英文混写场景下的同一类业务实体
直接拿通用 NER 模型往往不够;直接调用大模型做在线抽取又可能遇到成本、延迟、稳定性和审计问题。蒸馏的折中思路是:让大模型先当“标注专家”,再把能力迁移到小模型。
token-based distillation 的关键点
来源摘要提到的 token-based distillation,可以理解为让教师模型不只输出最终 JSON,而是对每个 token 或片段给出实体标签。这样学生模型学到的是更细粒度的边界判断能力。
一个典型标签体系可以采用 BIO 格式:
B-ORIGIN 起始站点
I-ORIGIN
B-DESTINATION 目的站点
I-DESTINATION
B-CARGO_TYPE 货物类型
I-CARGO_TYPE
B-TEMP_REQ 温控要求
I-TEMP_REQ
B-WEIGHT 重量
I-WEIGHT
O 非实体
双语 NER 的难点在于边界并不总是按空格切分。英文里 pharma shipment 是短语,中文里 冷链货物 没有天然空格,混写时 飞往 SIN 的 pharma cargo 又会出现跨语言上下文。token 级蒸馏的收益,正在于让模型学习“边界在哪里”,而不是只记住实体词表。
可以这样实践:用 Bedrock 生成蒸馏标注
下面示例演示一个可改造的最小流程:调用 Amazon Bedrock 上的 Claude 模型,把货运文本转换为 token 级 BIO 标注。运行前需要替换 AWS 区域和模型 ID,并确保本机已配置 AWS 凭证。
安装依赖:
pip install boto3
保存为 generate_ner_labels.py:
import json
import boto3
bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")
MODEL_ID = "anthropic.claude-3-haiku-20240307-v1:0"
texts = [
"2 PCS pharma shipment to FRA, temp 2-8C",
"请安排明早飞往新加坡的冷链货物,重量 120kg",
"ULD AKE12345EK offload at DXB",
]
label_schema = [
"B-ORIGIN", "I-ORIGIN",
"B-DESTINATION", "I-DESTINATION",
"B-CARGO_TYPE", "I-CARGO_TYPE",
"B-TEMP_REQ", "I-TEMP_REQ",
"B-WEIGHT", "I-WEIGHT",
"B-ULD", "I-ULD",
"B-ACTION", "I-ACTION",
"O",
]
prompt = f"""
You are labeling bilingual cargo logistics text for token-level NER distillation.
Return strict JSON only.
Allowed labels: {label_schema}
For each input text:
1. Split into practical tokens suitable for NER training.
2. Assign one BIO label per token.
3. Preserve the original token text.
Output format:
{{
"items": [
{{
"text": "...",
"tokens": [{{"token": "...", "label": "..."}}]
}}
]
}}
Input texts:
{json.dumps(texts, ensure_ascii=False)}
"""
body = {
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 1200,
"temperature": 0,
"messages": [
{"role": "user", "content": [{"type": "text", "text": prompt}]}
],
}
response = bedrock.invoke_model(
modelId=MODEL_ID,
body=json.dumps(body),
)
payload = json.loads(response["body"].read())
content = payload["content"][0]["text"]
print(content)
运行:
python generate_ner_labels.py > labeled_cargo_ner.json
这段代码不是完整生产流水线,但足够作为蒸馏数据生成的起点。实际落地时,建议增加三类校验:
- JSON schema 校验,拒绝格式错误输出
- 标签白名单校验,防止模型发明新标签
- 人工抽检队列,优先检查低置信、长文本、混合语言样本
从标注到部署:生产架构应保持克制
一个稳妥的部署架构通常分成离线和在线两部分。
离线侧:
原始货运文本
-> 清洗与脱敏
-> Bedrock 教师模型生成 token 标签
-> 规则与人工审核
-> 训练学生 NER 模型
-> 评估双语 F1、实体边界、业务字段召回
在线侧:
业务请求
-> 文本规范化
-> 学生 NER 模型推理
-> 业务规则后处理
-> 返回结构化实体
-> 监控漂移与失败样本
这里有一个重要取舍:教师模型不一定要在在线链路里。它更适合用于生成训练数据、处理疑难样本、周期性刷新数据集。在线链路交给小模型,可以降低延迟和成本,也更容易做版本管理、回归测试和合规审计。
如果需要保留大模型兜底,也应当把它设计成异步或低频路径,例如只处理学生模型置信度过低的样本,而不是每个请求都调用。
评估不能只看总体准确率
双语货运 NER 最容易被总体指标掩盖问题。模型可能在英文机场代码上表现很好,却在中文商品描述上频繁漏召;也可能识别出 120kg,却把温控条件 2-8C 标成普通文本。
更实用的评估切片包括:
- 按语言切分:英文、中文、混合文本
- 按实体类型切分:站点、重量、温控、ULD、动作
- 按文本来源切分:客户备注、操作日志、订舱信息
- 按错误类型切分:边界错误、标签错误、漏召、误召
可以用一个简单脚本检查标签分布是否异常:
import json
from collections import Counter
with open("labeled_cargo_ner.json", encoding="utf-8") as f:
data = json.load(f)
counter = Counter()
for item in data["items"]:
for token in item["tokens"]:
counter[token["label"]] += 1
for label, count in counter.most_common():
print(f"{label}\t{count}")
如果某些关键标签几乎没有出现,通常不是训练问题,而是样本覆盖、提示词约束或业务标签设计出了问题。
落地建议:先小闭环,再扩语种和实体
这类项目不要一开始就追求“识别所有货运实体”。更稳的路线是选 5 到 8 个高价值实体,覆盖一个明确业务流程,例如订舱、异常处理或温控货物审核。
上线前可以用这份清单压一遍:
- 标签定义是否足够清晰,业务人员能否独立判断
- 教师模型输出是否经过格式校验和抽检
- 学生模型是否按语言、实体、来源分别评估
- 在线链路是否能回收失败样本
- 是否有模型版本、数据版本和回滚机制
Amazon Bedrock 在这里扮演的是“可管理的大模型能力入口”。真正决定效果的,仍然是行业标签体系、token 级数据质量、评估切片和部署约束。把这些基础打牢,双语货运 NER 才能从演示走进生产系统。