3. 基于工单描述的故障现象结构化提取

为什么自由文本工单需要结构化

运维工单最初往往由值班员、船长或巡检人员在手机端或对讲记录中写成一段自由文本,例如:“3号浮标今天上午10点左右数据断了,风速和风向都没了,海流好像还在,现场浪比较大,船暂时靠不上去”。这段文字对人是可读的,但对检索、统计和派单匹配来说,故障现象、设备、观测要素、现场条件混在同一句话里,无法直接按字段筛选。结构化提取的任务,就是把这段话拆解成可入库、可查询的字段值,同时保留原文以便追溯。

本节采用“规则+词典+上下文线索”的轻量提取方案,不依赖大模型,适合在工单系统后台离线批处理。核心思路是:先按标点与连接词切分句子,再对每个分句做四类字段的匹配——故障现象(数据中断、数值异常、通信失败等)、涉及设备(浮标、风速传感器、CTD、数据采集器等)、观测要素(风速、风向、海流、盐度等)、现场条件(海况、天气、可接近性)。匹配结果按“字段→候选值→证据片段”组织,便于人工复核。

提取流程与字段映射关系

下图展示了一条工单从原始文本到结构化字段的映射路径。左侧是原文分句,中间是四类字段词典与线索规则,右侧是输出的结构化记录。注意“海流好像还在”这类表述会被识别为“未受影响要素”,与“故障现象”区分开,避免把正常要素误判为故障。

原始工单文本(分句) S1:3号浮标今天上午10点 左右数据断了 S2:风速和风向都没了 (观测要素缺失) S3:海流好像还在 (未受影响要素) S4:现场浪比较大 (海况条件) S5:船暂时靠不上去 (可接近性受限) 线索词: “断了/没了”→故障 “还在”→未受影响 字段词典与线索规则 故障现象 数据中断 / 数值异常 / 通信失败 传感器无输出 / 供电异常 线索:断了、没了、异常、失败 涉及设备 浮标 / 岸基站 / 风速传感器 CTD / 数据采集器 / 通信模块 线索:编号+设备名、型号 观测要素 风速 / 风向 / 海流 / 盐度 水温 / 波高 / 气压 线索:要素名+缺失/正常 现场条件 海况等级 / 天气 / 能见度 船舶可接近性 / 作业窗口 线索:浪大、风大、靠不上 结构化字段输出 fault_type 数据中断 证据:S1“数据断了” device 3号浮标 / 风速风向传感器 证据:S1“3号浮标”、S2 affected_elements 风速、风向 证据:S2“都没了” unaffected_elements 海流 证据:S3“好像还在” site_condition 浪大;船舶暂不可接近 证据:S4、S5 occur_time 当日 10:00 左右(相对时间)

提取规则的具体实现

下面给出一段可直接运行的 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_id3号浮标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 中,保证结构化不丢失可追溯性。