3. 基于工单描述的故障现象结构化提取
为什么自由文本工单需要结构化
运维工单最初往往由值班员、船长或巡检人员在手机端或对讲记录中写成一段自由文本,例如:“3号浮标今天上午10点左右数据断了,风速和风向都没了,海流好像还在,现场浪比较大,船暂时靠不上去”。这段文字对人是可读的,但对检索、统计和派单匹配来说,故障现象、设备、观测要素、现场条件混在同一句话里,无法直接按字段筛选。结构化提取的任务,就是把这段话拆解成可入库、可查询的字段值,同时保留原文以便追溯。
本节采用“规则+词典+上下文线索”的轻量提取方案,不依赖大模型,适合在工单系统后台离线批处理。核心思路是:先按标点与连接词切分句子,再对每个分句做四类字段的匹配——故障现象(数据中断、数值异常、通信失败等)、涉及设备(浮标、风速传感器、CTD、数据采集器等)、观测要素(风速、风向、海流、盐度等)、现场条件(海况、天气、可接近性)。匹配结果按“字段→候选值→证据片段”组织,便于人工复核。
提取流程与字段映射关系
下图展示了一条工单从原始文本到结构化字段的映射路径。左侧是原文分句,中间是四类字段词典与线索规则,右侧是输出的结构化记录。注意“海流好像还在”这类表述会被识别为“未受影响要素”,与“故障现象”区分开,避免把正常要素误判为故障。
提取规则的具体实现
下面给出一段可直接运行的 Python 实现。它把词典、线索词和分句逻辑封装成函数,输入一条工单文本,输出结构化字典。示例文本即上文那条浮标工单,运行后可直接看到各字段的提取结果与证据片段。
import re
# 1. 字段词典(可按实际站点设备扩充)
FAULT_WORDS = ["数据中断", "断了", "没了", "异常", "失败", "无输出", "掉线", "缺测"]
DEVICE_WORDS = ["浮标", "岸基站", "海上平台", "风速传感器", "风向传感器",
"CTD", "温盐深", "数据采集器", "通信模块", "太阳能板"]
ELEMENT_WORDS = ["风速", "风向", "海流", "盐度", "水温", "波高", "气压", "潮位"]
CONDITION_WORDS = ["浪大", "风大", "能见度低", "靠不上去", "无法登站", "作业窗口"]
# 2. 分句:按中文标点和连接词切分
def split_clauses(text):
parts = re.split(r"[,。;、,.;\n]|而且|但是|不过|同时", text)
return [p.strip() for p in parts if p.strip()]
# 3. 单字段匹配:返回命中的词与所在分句
def match_field(clauses, words):
hits = []
for c in clauses:
for w in words:
if w in c:
hits.append({"value": w, "evidence": c})
return hits
# 4. 主提取函数
def extract_workorder(text):
clauses = split_clauses(text)
result = {
"fault_type": match_field(clauses, FAULT_WORDS),
"device": match_field(clauses, DEVICE_WORDS),
"affected_elements": [],
"unaffected_elements": [],
"site_condition": match_field(clauses, CONDITION_WORDS),
"occur_time": None,
}
# 观测要素需区分“受影响”与“未受影响”
for c in clauses:
for w in ELEMENT_WORDS:
if w in c:
if any(k in c for k in ["还在", "正常", "未受影响"]):
result["unaffected_elements"].append({"value": w, "evidence": c})
else:
result["affected_elements"].append({"value": w, "evidence": c})
# 时间:抓取“上午/下午 + 数字点”
m = re.search(r"(上午|下午|凌晨|晚上)?\s*(\d{1,2})\s*点", text)
if m:
result["occur_time"] = f"{m.group(1) or ''}{m.group(2)}:00 左右"
return result
# 5. 示例运行
text = "3号浮标今天上午10点左右数据断了,风速和风向都没了,海流好像还在,现场浪比较大,船暂时靠不上去"
import json
print(json.dumps(extract_workorder(text), ensure_ascii=False, indent=2))
运行后 fault_type 会命中“断了”,device 命中“浮标”,affected_elements 得到“风速”“风向”,unaffected_elements 得到“海流”,site_condition 命中“浪大”“靠不上去”,occur_time 得到“上午10:00 左右”。每条结果都带 evidence 原文片段,方便人工核对是否误提。
FAULT_WORDS 等列表中,再重跑历史工单做抽样校验。结果校验与常见误提
规则提取最容易出问题的地方有三类,需要在入库前做校验:
- 要素归属误判:如“风速和风向都没了,海流好像还在”,若不分句直接匹配,可能把“海流”也归入受影响要素。分句后按“还在/正常”线索区分,可避免。
- 设备名与站点名混淆:“3号浮标”中的“浮标”是设备类型,编号“3号”应单独抽出作为站点标识,不能只留“浮标”这个泛称。
- 时间表述不完整:“今天上午10点”是相对时间,入库时应结合工单提交时间换算为绝对时间,否则跨天检索会错位。
校验方式建议:对每条工单的结构化结果,检查 fault_type 与 affected_elements 是否同时非空(有故障却无要素,或反之,都提示可能漏提);再抽查 evidence 是否确实包含对应 value,防止子串误命中(如“无风”被“风”命中)。
confidence 或 certainty 标记,把“好像”“可能”“大概”等词识别为低置信度,供后续派单时人工确认。可直接使用的字段提取结果表
下表是上述示例工单经提取后建议入库的字段结构,可作为工单系统结构化字段设计的参考:
| 字段名 | 示例值 | 来源分句 | 置信度 |
|---|---|---|---|
| station_id | 3号浮标 | S1 | 高 |
| fault_type | 数据中断 | S1“数据断了” | 高 |
| device | 风速风向传感器 | S2 | 中(未给型号) |
| affected_elements | 风速、风向 | S2“都没了” | 高 |
| unaffected_elements | 海流 | S3“好像还在” | 低(含“好像”) |
| site_condition | 浪大;船舶暂不可接近 | S4、S5 | 高 |
| occur_time | 当日 10:00 左右 | S1 | 中(相对时间) |
这张表的价值在于:后续检索“风速故障”时可直接按 affected_elements 命中;派单匹配时可用 site_condition 判断是否需要等待海况好转;统计“数据中断”频次时按 fault_type 聚合。原文与证据片段保留在 evidence 中,保证结构化不丢失可追溯性。